Tutorials Logic, IN info@tutorialslogic.com

C Sorting Algorithms Bubble, Merge, Quick Sort

Sorting Algorithms Overview

Sorting is one of the most fundamental operations in programming. Understanding how different sorting algorithms work - and their trade-offs - is essential for writing efficient C programs.

Algorithm Best Average Worst Space Stable?
Bubble Sort O(n) O(n^2) O(n^2) O(1) Yes
Selection Sort O(n^2) O(n^2) O(n^2) O(1) No
Insertion Sort O(n) O(n^2) O(n^2) O(1) Yes
Merge Sort O(n log n) O(n log n) O(n log n) O(n) Yes
Quick Sort O(n log n) O(n log n) O(n^2) O(log n) No

1. Bubble Sort

Repeatedly compares adjacent elements and swaps them if they are in the wrong order. Each pass "bubbles" the largest unsorted element to its correct position.

Bubble Sort

Bubble Sort
#include <stdio.h>

void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        int swapped = 0;
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                // swap
                int temp  = arr[j];
                arr[j]    = arr[j + 1];
                arr[j + 1] = temp;
                swapped = 1;
            }
        }
        if (!swapped) break;  // already sorted - early exit
    }
}

void printArray(int arr[], int n) {
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");
}

int main() {
    int arr[] = {64, 34, 25, 12, 22, 11, 90};
    int n = 7;
    printf("Before: "); printArray(arr, n);
    bubbleSort(arr, n);
    printf("After:  "); printArray(arr, n);
    return 0;
}
// After: 11 12 22 25 34 64 90

2. Selection Sort

Finds the minimum element in the unsorted portion and places it at the beginning. Makes exactly n-1 swaps - good when writes are expensive.

Selection Sort

Selection Sort
#include <stdio.h>

void selectionSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        int minIdx = i;
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[minIdx]) minIdx = j;
        }
        if (minIdx != i) {
            int temp    = arr[i];
            arr[i]      = arr[minIdx];
            arr[minIdx] = temp;
        }
    }
}

int main() {
    int arr[] = {29, 10, 14, 37, 13};
    int n = 5;
    selectionSort(arr, n);
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");  // 10 13 14 29 37
    return 0;
}

3. Insertion Sort

Builds the sorted array one element at a time by inserting each new element into its correct position. Very efficient for small or nearly-sorted arrays.

Insertion Sort

Insertion Sort
#include <stdio.h>

void insertionSort(int arr[], int n) {
    for (int i = 1; i < n; i++) {
        int key = arr[i];
        int j   = i - 1;
        // shift elements greater than key one position right
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

int main() {
    int arr[] = {12, 11, 13, 5, 6};
    int n = 5;
    insertionSort(arr, n);
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");  // 5 6 11 12 13
    return 0;
}

4. Merge Sort

Divide-and-conquer algorithm. Splits the array in half, recursively sorts each half, then merges them. Guaranteed O(n log n) - the go-to for stable, predictable sorting.

Merge Sort

Merge Sort
#include <stdio.h>
#include <stdlib.h>

void merge(int arr[], int left, int mid, int right) {
    int n1 = mid - left + 1;
    int n2 = right - mid;

    int *L = malloc(n1 * sizeof(int));
    int *R = malloc(n2 * sizeof(int));

    for (int i = 0; i < n1; i++) L[i] = arr[left + i];
    for (int j = 0; j < n2; j++) R[j] = arr[mid + 1 + j];

    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) arr[k++] = L[i++];
        else               arr[k++] = R[j++];
    }
    while (i < n1) arr[k++] = L[i++];
    while (j < n2) arr[k++] = R[j++];

    free(L); free(R);
}

void mergeSort(int arr[], int left, int right) {
    if (left < right) {
        int mid = left + (right - left) / 2;
        mergeSort(arr, left, mid);
        mergeSort(arr, mid + 1, right);
        merge(arr, left, mid, right);
    }
}

int main() {
    int arr[] = {38, 27, 43, 3, 9, 82, 10};
    int n = 7;
    mergeSort(arr, 0, n - 1);
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");  // 3 9 10 27 38 43 82
    return 0;
}

5. Quick Sort

Picks a pivot element and partitions the array so all elements less than the pivot come before it and all greater come after. Recursively sorts both partitions. Fastest in practice for most inputs.

Quick Sort

Quick Sort
#include <stdio.h>

void swap(int *a, int *b) {
    int t = *a; *a = *b; *b = t;
}

int partition(int arr[], int low, int high) {
    int pivot = arr[high];  // last element as pivot
    int i = low - 1;

    for (int j = low; j < high; j++) {
        if (arr[j] <= pivot) {
            i++;
            swap(&arr[i], &arr[j]);
        }
    }
    swap(&arr[i + 1], &arr[high]);
    return i + 1;
}

void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

int main() {
    int arr[] = {10, 7, 8, 9, 1, 5};
    int n = 6;
    quickSort(arr, 0, n - 1);
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");  // 1 5 7 8 9 10
    return 0;
}
Before you move on

C Sorting Algorithms Bubble, Merge, Quick Sort Mastery Check

5 checks
  • Sorting is one of the most fundamental operations in programming.
  • Understanding how different sorting algorithms work - and their trade-offs - is essential for writing efficient C programs.
  • Repeatedly compares adjacent elements and swaps them if they are in the wrong order.
  • Each pass "bubbles" the largest unsorted element to its correct position.
  • Finds the minimum element in the unsorted portion and places it at the beginning.

Sorting Failure Boundary

  • Incorrect loop bounds

    A comparison that reaches index n reads outside the array. Test zero, one, duplicate, sorted, and reverse-sorted inputs and verify both order and element preservation.

C Language Questions Learners Ask

A swap flag records whether the current pass changed anything.

Comparing a[i] with a[i + 1] requires i + 1 to remain below the array length. A loop that reaches the final index reads beyond the array, causing undefined behavior.

Returning *(int*)a - *(int*)b can overflow for extreme integers, violating the comparator contract. Compare explicitly and return -1, 0, or 1.

Next Step
Next Practice

Finish the concept here, then reinforce it with hands-on coding, interview prep, or a tool that matches the topic.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.