Sorting Algorithms and Binary Search: A Comprehensive Guide

Bubble Sort

Bubble sort works by repeatedly swapping adjacent elements if they are in the wrong order. Each pass through the list places the next largest element in its correct position. This process continues until the entire list is sorted.

Selection Sort

Selection sort divides the input list into a sorted and an unsorted region. It repeatedly selects the smallest (or largest) element from the unsorted region and moves it to the end of the sorted region.

Insertion Sort

Insertion sort builds the final sorted array one item at a time. It takes each element from the input and inserts it into its correct position in the growing sorted portion.

Shell Sort

Shell sort is an optimization of insertion sort that allows the exchange of items that are far apart. It starts by sorting elements that are distant from each other and progressively reduces the gap between elements to be compared.

Quick Sort

Quick sort is a divide-and-conquer algorithm that selects a 'pivot' element and partitions the array around the pivot. Elements smaller then the pivot go to its left, and larger elements go to its right. The process is then applied recursively to the sub-arrays.

Merge Sort

Merge sort is another divide-and-conquer algorithm that divides the array into two halves, recursively sorts each half, and then merges the two sorted halves back together.

Heap Sort

Heap sort first transforms the array in to a max-heap, where the largest element is at the root. It repeatedly swaps the root with the last element, reduces the heap size, and heapifies the root to maintain the heap property.

Counting Sort

Counting sort works by counting the occurrences of each unique element in the input array and using those counts to compute the positions of elements in the sorted output.

Implementation of Sorting Algorithms

Bubble Sort Implementation

Time Complexity: O(n²)

public static void bubbleSort(int[] data) {
    int n = data.length;
    for (pass = 0; pass < n - 1; pass++) {
        for (current = 0; current < n - pass - 1; current++) {
            if (data[current] > data[current + 1]) {
                // Swap elements
                int temporary = data[current];
                data[current] = data[current + 1];
                data[current + 1] = temporary;
            }
        }
    }
}

Selection Sort Implementation

Time Complexity: O(n²)

public static void selectionSort(int[] array) {
    int length = array.length;
    
    for (position = 0; position < length - 1; position++) {
        int minIndex = position;
        
        // Find the minimum element in the remaining unsorted array
        for (scan = position + 1; scan < length; scan++) {
            if (array[scan] < array[minIndex]) {
                minIndex = scan;
            }
        }
        
        // Swap the found minimum element with the current position
        if (minIndex != position) {
            int swapTemp = array[position];
            array[position] = array[minIndex];
            array[minIndex] = swapTemp;
        }
    }
}

Quick Sort Implementation

Time Complexity: O(n log n) average case, O(n²) worst case

public static void quickSort(int[] values, int leftBound, int rightBound) {
    if (leftBound >= rightBound) {
        return;
    }
    
    // Select pivot element (leftmost element)
    int pivot = values[leftBound];
    int rightPointer = rightBound;
    int leftPointer = leftBound;
    
    while (leftPointer != rightPointer) {
        // Move right pointer left until finding element smaller than pivot
        while (values[rightPointer] >= pivot && leftPointer < rightPointer) {
            rightPointer--;
        }
        
        // Move left pointer right until finding element larger than pivot
        while (values[leftPointer] <= pivot && leftPointer < rightPointer) {
            leftPointer++;
        }
        
        // Swap elements at left and right pointers
        if (leftPointer < rightPointer) {
            int temp = values[leftPointer];
            values[leftPointer] = values[rightPointer];
            values[rightPointer] = temp;
        }
    }
    
    // Swap pivot with the meeting point
    values[leftBound] = values[leftPointer];
    values[leftPointer] = pivot;
    
    // Recursively sort left and right partitions
    quickSort(values, leftBound, leftPointer - 1);
    quickSort(values, leftPointer + 1, rightBound);
}

Merge Sort Implementation

Time Complexity: O(n log n)

public class MergeSort {
    public static void main(String[] args) {
        int[] numbers = { 9, 8, 7, 6, 5, 4, 3, 2, 10 };
        int[] sortedNumbers = mergeSort(numbers, 0, numbers.length - 1);
        System.out.println(Arrays.toString(sortedNumbers));
    }

    public static int[] mergeSort(int[] numbers, int left, int right) {
        if (left == right) {
            return new int[] { numbers[left] };
        }

        // Divide the array
        int mid = left + (right - left) / 2;
        int[] leftPart = mergeSort(numbers, left, mid);
        int[] rightPart = mergeSort(numbers, mid + 1, right);
        int[] mergedArray = new int[leftPart.length + rightPart.length];

        // Merge the sorted parts
        int mergeIndex = 0, leftIndex = 0, rightIndex = 0;
        while (leftIndex < leftPart.length && rightIndex < rightPart.length) {
            mergedArray[mergeIndex++] = leftPart[leftIndex] < rightPart[rightIndex] 
                ? leftPart[leftIndex++] : rightPart[rightIndex++];
        }
        
        // Copy remaining elements
        while (leftIndex < leftPart.length) {
            mergedArray[mergeIndex++] = leftPart[leftIndex++];
        }
        while (rightIndex < rightPart.length) {
            mergedArray[mergeIndex++] = rightPart[rightIndex++];
        }
        
        return mergedArray;
    }
}

Heap Sort Implementation

Time Complexity: O(n log n)

public class HeapSort {
    public static void main(String[] args) {
        int[] data = {5, 7, 4, 2, 0, 3, 1, 6};
        
        // Build max heap
        for (int i = data.length - 1; i >= 0; i--) {
            heapify(data, i, data.length);
        }
        System.out.println("Max heap: " + Arrays.toString(data));
        
        // Extract elements from heap
        for (int i = data.length - 1; i >= 0; i--) {
            // Swap root with last element
            int temp = data[i];
            data[i] = data[0];
            data[0] = temp;
            
            // Heapify the reduced heap
            heapify(data, 0, i);
        }
        
        System.out.println("Sorted array: " + Arrays.toString(data));
    }
    
    private static void heapify(int[] array, int parent, int length) {
        int child = parent * 2 + 1; // Left child
        
        while (child < length) {
            int rightChild = child + 1; // Right child
            
            // Find the larger child
            if (rightChild < length && array[child] < array[rightChild]) {
                child = rightChild;
            }
            
            // If parent is smaller than child, swap
            if (array[parent] < array[child]) {
                int temp = array[parent];
                array[parent] = array[child];
                array[child] = temp;
                
                // Move down to child position
                parent = child;
                child = parent * 2 + 1;
            } else {
                break; // Heap property is satisfied
            }
        }
    }
}

Binary Search Implementation

Time Complexity: O(log n)

public class BinarySearch {
    public static void main(String[] args) {
        int[] sortedArray = {3, 45, 56, 57, 67, 88};
        int targetValue = 11;
        int result = binarySearch(sortedArray, targetValue);
        
        if (result != -1) {
            System.out.println("Element found at index: " + result);
        } else {
            System.out.println("Element not found in the array");
        }
    }
    
    public static int binarySearch(int[] array, int target) {
        int lowerBound = 0;
        int upperBound = array.length - 1;
        
        while (lowerBound <= upperBound) {
            int midPoint = lowerBound + (upperBound - lowerBound) / 2;
            
            if (target == array[midPoint]) {
                return midPoint; // Target found
            } else if (target < array[midPoint]) {
                upperBound = midPoint - 1; // Search left half
            } else {
                lowerBound = midPoint + 1; // Search right half
            }
        }
        
        return -1; // Target not found
    }
}

Tags: sorting-algorithms data-structures bubble-sort selection-sort quick-sort

Posted on Sat, 12 Sep 2026 16:33:48 +0000 by egpis