Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Sorting Algorithms: Comprehensive Implementation Guide for Common Sorting Techniques

Tech May 18 2

Bubble Sort - O(N²)

Concept

Bubble sort works by repeatedly compairng adjcaent elements and swapping them if they're in wrong order. For ascending order, each pass moves the largest unsorted element to its correct position at the end of the array.

Implementation

void bubble_sort(int* arr, int size) {
    for (int round = 0; round < size - 1; round++) {
        for (int idx = 0; idx < size - 1 - round; idx++) {
            if (arr[idx] > arr[idx + 1]) {
                int temp = arr[idx];
                arr[idx] = arr[idx + 1];
                arr[idx + 1] = temp;
            }
        }
    }
}

The time complexity remains O(N²).

Selection Sort - O(N²)

Concept

Selection sort finds the minimum element in the unsorted portion and places it at the beginning. An optimized version finds both minimum and maximum in each pass, placing them at both ends.

Implementation

void selection_sort(int* arr, int size) {
    int start = 0, finish = size - 1;
    
    while (start < finish) {
        int min_idx = start, max_idx = start;
        
        for (int current = start; current <= finish; current++) {
            if (arr[current] < arr[min_idx]) {
                min_idx = current;
            }
            if (arr[current] > arr[max_idx]) {
                max_idx = current;
            }
        }
        
        // Swap minimum to start
        int temp = arr[start];
        arr[start] = arr[min_idx];
        arr[min_idx] = temp;
        
        // Handle case where max was originally at start position
        if (finish == min_idx) {
            max_idx = min_idx;
        }
        
        // Swap maximum to end
        temp = arr[finish];
        arr[finish] = arr[max_idx];
        arr[max_idx] = temp;
        
        start++;
        finish--;
    }
}

Time complexity is O(N²).

Insertion Sort - O(N²)

Concept

Insertion sort builds the sorted array one element at a time. It takes each element and inserts it into its correct position among the already sorted elements.

Implementation

void insertion_sort(int* arr, int size) {
    for (int boundary = 0; boundary < size - 1; boundary++) {
        int next_val = arr[boundary + 1];
        int pos = boundary;
        
        while (pos >= 0 && arr[pos] > next_val) {
            arr[pos + 1] = arr[pos];
            pos--;
        }
        
        arr[pos + 1] = next_val;
    }
}

Time complexity is O(N²).

Shell Sort

Concept

Shell sort improves insertion sort by allowing exchanges of elemants far apart. It uses a gap sequence that starts large and reduces to 1, effectively making it an optimized insertion sort.

Implementation

void shell_sort(int* arr, int size) {
    int gap = size;
    
    while (gap > 1) {
        gap = gap / 3 + 1;
        
        for (int start = 0; start < gap; start++) {
            for (int current = start; current < size - gap; current += gap) {
                int next_val = arr[current + gap];
                int pos = current;
                
                while (pos >= 0 && arr[pos] > next_val) {
                    arr[pos + gap] = arr[pos];
                    pos -= gap;
                }
                
                arr[pos + gap] = next_val;
            }
        }
    }
}

Time complexity is approximately O(N^1.3).

Heap Sort - O(N log N)

Concept

Heap sort builds a max heap from the array, then repeatedly extracts the maximum element (root) and places it at the end of the array.

Implementation

void heapify_down(int* arr, int size, int root) {
    int parent = root;
    int child = parent * 2 + 1;
    
    while (child < size) {
        if (child + 1 < size && arr[child] < arr[child + 1]) {
            child++;
        }
        
        if (arr[child] > arr[parent]) {
            int temp = arr[child];
            arr[child] = arr[parent];
            arr[parent] = temp;
            
            parent = child;
            child = parent * 2 + 1;
        } else {
            break;
        }
    }
}

void heap_sort(int* arr, int size) {
    // Build max heap
    for (int i = (size - 2) / 2; i >= 0; i--) {
        heapify_down(arr, size, i);
    }
    
    // Extract elements from heap
    for (int end = size - 1; end > 0; end--) {
        int temp = arr[0];
        arr[0] = arr[end];
        arr[end] = temp;
        
        heapify_down(arr, end, 0);
    }
}

Time complexity is O(N log N).

Quick Sort - O(N log N)

Hoare Partition Method

Quick sort selects a pivot element and partitions the array so that elements smaller than the pivot come before it, and larger elements come after it.

int hoare_partition(int* arr, int low, int high) {
    int pivot = arr[low];
    int left = low, right = high;
    
    while (left < right) {
        while (left < right && arr[right] >= pivot) {
            right--;
        }
        while (left < right && arr[left] <= pivot) {
            left++;
        }
        
        if (left < right) {
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
        }
    }
    
    int temp = arr[low];
    arr[low] = arr[left];
    arr[left] = temp;
    
    return left;
}

void quick_sort_hoare(int* arr, int low, int high) {
    if (low >= high) return;
    
    int partition_idx = hoare_partition(arr, low, high);
    quick_sort_hoare(arr, low, partition_idx - 1);
    quick_sort_hoare(arr, partition_idx + 1, high);
}

Three-Way Median Optimization

int median_of_three(int* arr, int low, int high) {
    int mid = low + (high - low) / 2;
    
    if (arr[low] > arr[mid]) {
        if (arr[mid] > arr[high]) {
            return mid;
        } else if (arr[low] > arr[high]) {
            return high;
        } else {
            return low;
        }
    } else {
        if (arr[low] > arr[high]) {
            return low;
        } else if (arr[mid] > arr[high]) {
            return high;
        } else {
            return mid;
        }
    }
}

Merge Sort - O(N log N)

Concept

Merge sort divides the array into halves recursively until single elements remain, then merges the sorted halves back together.

Implementation

void merge_arrays(int* arr, int* temp, int left, int mid, int right) {
    int i = left, j = mid + 1, k = left;
    
    while (i <= mid && j <= right) {
        if (arr[i] <= arr[j]) {
            temp[k++] = arr[i++];
        } else {
            temp[k++] = arr[j++];
        }
    }
    
    while (i <= mid) {
        temp[k++] = arr[i++];
    }
    
    while (j <= right) {
        temp[k++] = arr[j++];
    }
    
    for (i = left; i <= right; i++) {
        arr[i] = temp[i];
    }
}

void merge_sort_recursive(int* arr, int* temp, int left, int right) {
    if (left >= right) return;
    
    int mid = left + (right - left) / 2;
    merge_sort_recursive(arr, temp, left, mid);
    merge_sort_recursive(arr, temp, mid + 1, right);
    merge_arrays(arr, temp, left, mid, right);
}

void merge_sort(int* arr, int size) {
    int* temp = malloc(size * sizeof(int));
    if (!temp) return;
    
    merge_sort_recursive(arr, temp, 0, size - 1);
    free(temp);
}

Counting Sort

Concept

Counting sort counts occurrences of each value and reconstructs the sorted array based on these counts. It's efficient when the range of values is not significantly greater than the number of elements.

Implementation

void counting_sort(int* arr, int size) {
    int max_val = arr[0], min_val = arr[0];
    
    for (int i = 1; i < size; i++) {
        if (arr[i] > max_val) max_val = arr[i];
        if (arr[i] < min_val) min_val = arr[i];
    }
    
    int range = max_val - min_val + 1;
    int* count = calloc(range, sizeof(int));
    if (!count) return;
    
    for (int i = 0; i < size; i++) {
        count[arr[i] - min_val]++;
    }
    
    int index = 0;
    for (int val = 0; val < range; val++) {
        while (count[val]-- > 0) {
            arr[index++] = val + min_val;
        }
    }
    
    free(count);
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.