Algorithms Reference Guide
Algorithms Reference Guide
Sorting Algorithms
1.1 Bubble Sort
IN SIMPLE WORDS
Imagine people standing in a line, and you compare each pair of neighbours, swapping them if the one in front is bigger than the one behind.
Repeat this walk down the line again and again — the biggest values slowly "bubble" to the end.
Description
Bubble Sort repeatedly steps through the array, compares each pair of adjacent elements, and swaps them if they are in the wrong order.
The largest unsorted element "bubbles up" to its correct position on every pass.
Step-by-step working:
1. Start at the beginning of the array.
2. Compare each pair of adjacent elements.
3. If the left element is greater than the right one, swap them.
4. Continue to the end of the array — this completes one pass, placing the largest element at the end.
5. Repeat the passes for the remaining unsorted portion of the array.
6. Stop early if a full pass completes with no swaps — the array is already sorted.
Java Implementation
bubbleSort(arr);
Program Output
Original array: 64 34 25 12 22 11 90
Sorted array: 11 12 22 25 34 64 90
Note: The best case occurs on an already-sorted array because of the swap flag that allows early termination.
1.2 Selection Sort
IN SIMPLE WORDS
Imagine you keep picking out the smallest remaining item from a messy pile and placing it into a new, growing line — one item at a time, always
taking the smallest one left in the pile.
Description
Selection Sort divides the array into a sorted and an unsorted region. On every iteration it selects the smallest element from the unsorted
region and moves it to the end of the sorted region.
Step-by-step working:
1. Set the first element as the current minimum position.
2. Scan the remaining unsorted elements to find the smallest value.
3. Swap the smallest value found with the element at the current minimum position.
4. Move the boundary between sorted and unsorted regions one step forward.
5. Repeat until the entire array is sorted.
Java Implementation
selectionSort(arr);
Program Output
Original array: 64 25 12 22 11
Sorted array: 11 12 22 25 64
Note: Selection Sort always performs the same number of comparisons regardless of input order, so its best and worst cases are identical.
1.3 Insertion Sort
IN SIMPLE WORDS
Just like sorting playing cards in your hand — you pick up one card at a time from the table and slide it into its correct place among the cards you
are already holding in order.
Description
Insertion Sort builds the final sorted array one element at a time. It takes each new element and inserts it into its correct position among
the already-sorted elements to its left, similar to how a person sorts playing cards in hand.
Step-by-step working:
1. Consider the first element to already be a sorted sub-array of size one.
2. Pick the next element as the "key".
3. Compare the key with elements in the sorted sub-array from right to left.
4. Shift every element greater than the key one position to the right.
5. Insert the key into the resulting gap.
6. Repeat for all remaining elements in the array.
Java Implementation
insertionSort(arr);
Program Output
Original array: 12 11 13 5 6
Sorted array: 5 6 11 12 13
Note: Very efficient for small or nearly-sorted datasets; the best case occurs when the input is already sorted.
1.4 Merge Sort
IN SIMPLE WORDS
Like splitting a deck of cards in half again and again until each pile has only one card, and then repeatedly combining piles back together in the
correct order until the full deck is sorted.
Description
Merge Sort is a divide-and-conquer algorithm. It recursively splits the array into halves until each piece has one element, then merges the
pieces back together in sorted order.
Step-by-step working:
1. If the array has more than one element, find the middle point to divide it into two halves.
2. Recursively call Merge Sort on the left half.
3. Recursively call Merge Sort on the right half.
4. Merge the two sorted halves back into a single sorted sequence by repeatedly picking the smaller of the two front elements.
5. Copy any remaining elements from either half once the other is exhausted.
Java Implementation
static void merge(int[] arr, int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;
int i = 0, j = 0, k = left;
while (i < n1 && j < n2) {
if (leftArr[i] <= rightArr[j]) {
arr[k++] = leftArr[i++];
} else {
arr[k++] = rightArr[j++];
}
}
while (i < n1) arr[k++] = leftArr[i++];
while (j < n2) arr[k++] = rightArr[j++];
}
Program Output
Original array: 38 27 43 3 9 82 10
Sorted array: 3 9 10 27 38 43 82
Note: Guarantees O(n log n) performance in every case, which makes it a reliable choice for large datasets, at the cost of extra memory for the merge step.
1.5 Quick Sort
IN SIMPLE WORDS
Pick one person as a reference point, then ask everyone shorter to stand on one side and everyone taller to stand on the other side. Repeat this
same trick separately within each side until everyone is in order.
Description
Quick Sort is a divide-and-conquer algorithm that picks a "pivot" element and partitions the array so that smaller elements land to its left
and larger elements to its right, then recursively sorts each partition.
Step-by-step working:
1. Choose a pivot element (this implementation uses the last element of the range).
2. Partition the array: move all elements smaller than the pivot before it, and all larger elements after it.
3. The pivot is now in its final sorted position.
4. Recursively apply the same process to the sub-array on the left of the pivot.
5. Recursively apply the same process to the sub-array on the right of the pivot.
Java Implementation
Program Output
Original array: 10 7 8 9 1 5
Sorted array: 1 5 7 8 9 10
Note: The worst case (O(n^2)) happens on already-sorted or reverse-sorted input with a poor pivot choice; randomized or median-of-three pivot selection
reduces this risk in practice.
1.6 Heap Sort
IN SIMPLE WORDS
Picture a group of people arranged so the tallest is always at the front. Keep pulling out the tallest person, place them at the end of the final line,
and rearrange what's left so the next tallest again comes to the front.
Description
Heap Sort first transforms the array into a max-heap, a binary tree structure where every parent node is greater than or equal to its
children. It then repeatedly removes the largest element (the root) and rebuilds the heap.
Step-by-step working:
1. Build a max-heap from the input array.
2. Swap the root of the heap (the largest element) with the last element of the array.
3. Reduce the heap size by one, excluding the now-sorted last element.
4. "Heapify" the root to restore the max-heap property.
5. Repeat the swap-and-heapify steps until the heap size is one.
Java Implementation
if (largest != i) {
int swap = arr[i];
arr[i] = arr[largest];
arr[largest] = swap;
heapify(arr, n, largest);
}
}
heapSort(arr);
Program Output
Original array: 12 11 13 5 6 7
Sorted array: 5 6 7 11 12 13
Note: Consistently guarantees O(n log n) time with only constant extra space, making it attractive when memory is limited.
1.7 Shell Sort
IN SIMPLE WORDS
Like Insertion Sort, but instead of only comparing neighbours, you first compare people standing far apart, gradually bringing them closer
together in later rounds — fixing big mistakes early so later steps have less work to do.
Description
Shell Sort is a generalisation of Insertion Sort that first compares elements far apart from each other (using a "gap") and progressively
reduces the gap, allowing elements to move faster toward their correct position.
Step-by-step working:
1. Choose an initial gap value, typically n / 2.
2. Compare elements that are 'gap' positions apart and perform an insertion-sort-style shift for each such pair.
3. Reduce the gap (this implementation halves it each round).
4. Repeat the gapped insertion sort with the smaller gap.
5. Continue until the gap becomes 1, which performs a final, now nearly-effortless, standard insertion sort.
Java Implementation
shellSort(arr);
Program Output
Original array: 23 29 15 19 31 7 9 5 2
Sorted array: 2 5 7 9 15 19 23 29 31
Note: Performance depends heavily on the chosen gap sequence; the classic n/2 halving sequence used here gives good practical performance, though
better sequences (e.g. Knuth's) can push the average case lower.
1.8 Counting Sort
IN SIMPLE WORDS
Like counting how many students scored each mark in a class test, and then listing the students out from the lowest mark to the highest based
purely on those counts — without ever comparing two students directly.
Description
Counting Sort is a non-comparison sort that works by counting how many times each distinct value appears, then using those counts to
place every element directly into its final sorted position.
Step-by-step working:
1. Find the minimum and maximum values in the array to determine the value range.
2. Create a count array sized to that range and tally the occurrences of every value.
3. Transform the count array into a running total (prefix sum) so each cell holds the position where that value's block ends.
4. Walk the original array from right to left, placing each element into the output array at the position given by the prefix sums,
decrementing the count as you go.
5. Copy the output array back over the original array.
Java Implementation
countingSort(arr);
Program Output
Original array: 4 2 2 8 3 3 1
Sorted array: 1 2 2 3 3 4 8
Note: Here k is the range of input values. Extremely fast when k is comparable to n, but memory and time both grow with the value range, so it is unsuitable
for widely-spread values.
1.9 Radix Sort
IN SIMPLE WORDS
Like sorting a stack of mail by postal code — first arranging by the last digit, then by the second-last digit, and so on, until the leftmost digit has
been used, leaving the whole stack fully sorted.
Description
Radix Sort sorts integers digit by digit, from the least significant digit to the most significant, using a stable sort (Counting Sort) as a
subroutine at each digit position.
Step-by-step working:
1. Find the maximum value in the array to determine the number of digits to process.
2. Starting with the least significant digit (units place), sort the entire array using a stable counting sort based on that digit.
3. Move to the next digit (tens, then hundreds, and so on) and repeat the stable sort.
4. Continue until every digit position up to the maximum number of digits has been processed.
5. The array is fully sorted once the most significant digit has been processed.
Java Implementation
radixSort(arr);
Program Output
Note: Here d is the number of digits in the largest number and b is the base (10 in this implementation). Because d is typically small and constant, Radix Sort
behaves close to linear time for fixed-width integers.
1.10 Bucket Sort
IN SIMPLE WORDS
Like sorting fruit by size into separate baskets first, then quickly arranging the few pieces inside each basket, and finally lining up the baskets in
order — much less work than sorting everything together at once.
Description
Bucket Sort distributes elements into a number of "buckets" based on their value, sorts each bucket individually (typically with a simple
sort), and then concatenates the buckets in order. It works best on uniformly distributed floating-point data in a known range.
Step-by-step working:
1. Create an empty bucket for each element in the input (n buckets).
2. For every element, compute a bucket index based on its value and place the element into that bucket.
3. Sort the contents of each individual bucket (this implementation uses [Link] on each bucket's list).
4. Concatenate all the buckets in order to produce the final sorted array.
Java Implementation
import [Link];
import [Link];
import [Link];
int index = 0;
for (List<Double> bucket : buckets) {
for (double val : bucket) {
arr[index++] = val;
}
}
}
bucketSort(arr);
Program Output
Note: k is the number of buckets. The worst case occurs when all elements land in a single bucket; performance depends on how uniformly the input is
distributed.
Part II
Searching Algorithms
2.1 Linear Search
IN SIMPLE WORDS
Like scanning a shopping list from top to bottom to check if an item is on it — you check every single line, one after another, until you find it.
Description
Linear Search examines every element of the array one by one, in order, until it finds the target value or reaches the end of the array. It
requires no particular ordering of the data.
Step-by-step working:
1. Start from the first element of the array.
2. Compare the current element with the target value.
3. If they match, return the current index.
4. Otherwise, move to the next element.
5. If the end of the array is reached with no match, report that the element was not found.
Java Implementation
if (result != -1) {
[Link]("Element found at index: " + result);
} else {
[Link]("Element not found in the array.");
}
}
}
Program Output
Note: Works on unsorted data, but is inefficient for large datasets compared to search algorithms that exploit sorted order.
2.2 Binary Search
IN SIMPLE WORDS
Like looking up a word in a printed dictionary — you open it in the middle, see if your word comes before or after that page, and keep repeating
this halving trick until you land on the word.
Description
Binary Search operates on a sorted array. It repeatedly divides the search range in half, comparing the target with the middle element and
discarding the half of the array that cannot contain the target.
Step-by-step working:
1. Set low and high pointers to the start and end of the array.
2. Compute the middle index of the current range.
3. If the middle element equals the target, return its index.
4. If the target is greater than the middle element, discard the left half and search only the right half.
5. If the target is smaller, discard the right half and search only the left half.
6. Repeat until the element is found or the range becomes empty.
Java Implementation
[Link]("Sorted array: {11, 23, 34, 45, 56, 67, 78, 90}");
[Link]("Target: " + target);
if (result != -1) {
[Link]("Element found at index: " + result);
} else {
[Link]("Element not found in the array.");
}
}
}
Program Output
Sorted array: {11, 23, 34, 45, 56, 67, 78, 90}
Target: 56
Element found at index: 4
Note: Requires the array to be sorted beforehand. The iterative version used here keeps space usage constant, unlike a recursive implementation.
2.3 Jump Search
IN SIMPLE WORDS
Like flipping through a sorted phonebook in fixed jumps of a few pages at a time until you land near the name you want, and then reading page
by page from there.
Description
Jump Search works on sorted arrays by jumping ahead in fixed-size blocks to find the block that could contain the target, then performing
a linear scan within that block.
Step-by-step working:
1. Choose a block (jump) size, typically the square root of the array length.
2. Jump forward block by block until finding a block whose last element is greater than or equal to the target.
3. Perform a linear search within that block, starting from its first element.
4. If the target is found, return its index; otherwise report it is absent.
Java Implementation
[Link]("Sorted array: {2, 4, 8, 12, 17, 23, 29, 35, 42, 50, 61, 72}");
[Link]("Target: " + target);
if (result != -1) {
[Link]("Element found at index: " + result);
} else {
[Link]("Element not found in the array.");
}
}
}
Program Output
Sorted array: {2, 4, 8, 12, 17, 23, 29, 35, 42, 50, 61, 72}
Target: 42
Element found at index: 8
Note: A middle ground between Linear Search and Binary Search — faster than linear scanning while being simpler to reason about than repeated halving.
2.4 Interpolation Search
IN SIMPLE WORDS
Like opening a dictionary near the back if you are looking for a word starting with "Y", instead of always opening it exactly in the middle — you
guess a smarter starting point based on the value itself.
Description
Interpolation Search improves on Binary Search for uniformly distributed sorted data. Instead of always checking the middle element, it
estimates the likely position of the target using linear interpolation, similar to how a person looks up a name in a phone book.
Step-by-step working:
1. Confirm the target lies within the value range of the current low and high bounds.
2. Estimate the probable position of the target using the proportion of its value between the low and high values.
3. Compare the element at the estimated position with the target.
4. If it matches, return the index; otherwise narrow the search range above or below the estimated position, similar to Binary Search.
5. Repeat until the target is found or the range is exhausted.
Java Implementation
while (low <= high && target >= arr[low] && target <= arr[high]) {
if (low == high) {
if (arr[low] == target) return low;
return -1;
}
int pos = low + (int) (((long) (high - low) * (target - arr[low])) / (arr[high] - arr[low]));
[Link]("Sorted array: {10, 20, 25, 35, 42, 55, 63, 78, 84, 91}");
[Link]("Target: " + target);
if (result != -1) {
[Link]("Element found at index: " + result);
} else {
[Link]("Element not found in the array.");
}
}
}
Program Output
Sorted array: {10, 20, 25, 35, 42, 55, 63, 78, 84, 91}
Target: 63
Element found at index: 6
Note: Performs best on uniformly distributed data. Its worst case degrades to linear time when the data is very unevenly distributed.
2.5 Exponential Search
IN SIMPLE WORDS
Like taking bigger and bigger steps forward — 1, then 2, then 4, then 8 pages at a time — until you jump past where your target should be, then
carefully searching back within that last small range.
Description
Exponential Search finds a range in which the target may lie by repeatedly doubling an index, then performs a Binary Search within that
bounded range. It is especially useful for unbounded or very large sorted arrays.
Step-by-step working:
1. Check if the target is the first element; if so, return index 0.
2. Starting from index 1, repeatedly double the index while the element at that index is less than or equal to the target.
3. Once the doubling overshoots the target (or the array end), a valid range has been identified between the previous and current index.
4. Run Binary Search within that bounded range to locate the exact position of the target.
Java Implementation
static int binarySearch(int[] arr, int low, int high, int target) {
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == target) return mid;
else if (arr[mid] < target) low = mid + 1;
else high = mid - 1;
}
return -1;
}
int i = 1;
while (i < n && arr[i] <= target) {
i *= 2;
}
[Link]("Sorted array: {2, 5, 8, 12, 16, 23, 38, 45, 56, 72, 91}");
[Link]("Target: " + target);
if (result != -1) {
[Link]("Element found at index: " + result);
} else {
[Link]("Element not found in the array.");
}
}
}
Program Output
Sorted array: {2, 5, 8, 12, 16, 23, 38, 45, 56, 72, 91}
Target: 45
Element found at index: 7
Note: Particularly effective when the target is near the beginning of the array, or when the array size is unknown in advance.
2.6 Ternary Search
IN SIMPLE WORDS
Similar to Binary Search, but instead of splitting the list into two parts, you split it into three parts and check two marker points to decide which
third to continue searching in.
Description
Ternary Search operates on a sorted array by splitting the current range into three parts using two mid-points, then discarding the third of
the range that cannot contain the target.
Step-by-step working:
1. Compute two mid-points that divide the current range into three roughly equal parts.
2. Compare the target with the elements at both mid-points; return the index immediately on a match.
3. If the target is smaller than the first mid-point's value, search only the first third.
4. If the target is larger than the second mid-point's value, search only the last third.
5. Otherwise, search the middle third.
6. Repeat recursively until the target is found or the range becomes empty.
Java Implementation
static int ternarySearch(int[] arr, int low, int high, int target) {
if (high >= low) {
int mid1 = low + (high - low) / 3;
int mid2 = high - (high - low) / 3;
[Link]("Sorted array: {3, 7, 11, 19, 24, 30, 37, 45, 52, 60, 68}");
[Link]("Target: " + target);
if (result != -1) {
[Link]("Element found at index: " + result);
} else {
[Link]("Element not found in the array.");
}
}
}
Program Output
Sorted array: {3, 7, 11, 19, 24, 30, 37, 45, 52, 60, 68}
Target: 52
Element found at index: 8
IN SIMPLE WORDS
Very similar to Binary Search, but instead of always splitting exactly in half, it splits the list using Fibonacci numbers (1, 1, 2, 3, 5, 8, 13...) which
only needs addition and subtraction instead of division.
Description
Fibonacci Search is similar to Binary Search but divides the array using Fibonacci numbers instead of a simple midpoint, which can be
useful in systems where division operations are costly, since it relies only on addition and subtraction.
Step-by-step working:
1. Find the smallest Fibonacci number greater than or equal to the array length.
2. Use the Fibonacci numbers to mark a comparison point within the unexplored range.
3. If the element at that point is less than the target, shift the range forward and reduce to the next-smaller pair of Fibonacci numbers.
4. If it is greater than the target, reduce the range from the other side using a smaller pair of Fibonacci numbers.
5. If it matches the target, return the index.
6. Repeat until the Fibonacci numbers are reduced to a trivial case, then check any single remaining element.
Java Implementation
int fib2 = 0;
int fib1 = 1;
int fib = fib1 + fib2;
return -1;
}
[Link]("Sorted array: {10, 22, 35, 40, 45, 50, 80, 82, 85, 90, 100}");
[Link]("Target: " + target);
if (result != -1) {
[Link]("Element found at index: " + result);
} else {
[Link]("Element not found in the array.");
}
}
}
Program Output
Sorted array: {10, 22, 35, 40, 45, 50, 80, 82, 85, 90, 100}
Target: 85
Element found at index: 8
Note: Comparable in complexity to Binary Search, but historically advantageous on hardware or storage media where addition and subtraction are cheaper
than division.
— End of Document —