Sorting Algorithms in C: Comparison and Choosing a Method

Sorting algorithms in C rearrange values into an order; searching algorithms locate a value. Start with insertion sort to learn movement through an array, merge sort when stable worst-case O(n log n) sorting matters, and heap sort when you need a worst-case bound with constant auxiliary storage. No single algorithm is always fastest for every workload.

Unsorted bars become an ascending sequence through a glowing transition.

Comparison table

The table describes the specific ordinary implementations linked below, sorting in ascending order. Time counts treat comparisons and element moves as constant-cost. Auxiliary space excludes the input array but includes recursion. Stability means equal keys retain their original relative order.

Algorithm Best time Average time Worst time Auxiliary space Stable?
Bubble sort with early exit O(n) O(n²) O(n²) O(1) Yes, strict swaps
Insertion sort O(n) O(n²) O(n²) O(1) Yes, strict shifts
Selection sort O(n²) O(n²) O(n²) O(1) No, distant swaps
Quick sort O(n log n) O(n log n), under suitable input/pivot assumptions O(n²) O(log n) typical recursion, O(n) worst for naive recursion No
Merge sort O(n log n) O(n log n) O(n log n) O(n) buffer plus O(log n) stack Yes when left wins ties
Heap sort O(n) possible on all-equal input with early-return sift; O(n log n) usual distinct-key bound O(n log n) O(n log n) O(1), iterative sift No

“Average” requires a model of input order or randomized choices; it is not a guarantee for one dataset. Quick sort's last-element pivot can repeatedly make unbalanced partitions on sorted, reverse-sorted or duplicate-heavy input. All listed O bounds are upper bounds, not universal exact operation counts.

Choose by the requirement

  • Small or nearly sorted arrays: insertion sort is simple and does little shifting when there are few inversions.
  • Teaching adjacent comparisons: bubble sort makes swaps easy to trace, but avoid using it as a large-data default.
  • Few writes: selection sort makes few swaps while still doing quadratic comparisons; whether that helps depends on comparison and write costs.
  • Stable ordering: insertion or merge sort can preserve equal records; plain integer tests alone do not demonstrate record identity.
  • Bounded worst-case time and little extra memory: heap sort is a useful option, with no stability guarantee.
  • General-purpose library use: C provides qsort, but its name is not a language guarantee that it uses quick sort.

Complete library-sort example

Use qsort from stdlib.h when its API and unspecified equal-key ordering fit your task. C17 does not specify its sorting algorithm, stability, auxiliary space or a complexity guarantee. The comparator returns a negative value, zero or a positive value. Do not return a - b for arbitrary integers: that subtraction can overflow. The relational form below returns only -1, 0 or 1.

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

static int compare_ints(const void *left, const void *right) {
    int a = *(const int *)left;
    int b = *(const int *)right;
    return (a > b) - (a < b);
}

int main(void) {
    int values[] = {64, 34, 25, 12, 22};
    size_t count = sizeof values / sizeof values[0];
    qsort(values, count, sizeof values[0], compare_ints);
    for (size_t i = 0; i < count; ++i) {
        printf("%s%d", i == 0 ? "" : " ", values[i]);
    }
    putchar('\n');
    return 0;
}

Run standard-library qsort online

Expected output

Reference output for the displayed program, not a live execution result.

12 22 25 34 64

The pointer arguments identify elements of the original array. sizeof values[0] tells the library the size of each element. The comparator must impose a consistent ordering; changing the keys while comparing them or returning contradictory results violates that requirement. Sorting a structure by one field needs a comparator for that structure, not an unsafe cast to an unrelated type.

Learn with one input, then edge cases

For each linked algorithm, trace {64, 34, 25, 12, 22} and compare intermediate states, not only the shared final output 12 22 25 34 64. Then test empty input through a valid function call, one value, already sorted, reverse order, all equal, repeated negatives and integer extremes. A zero-length array declaration is not standard C.

For stable record sorts, add unique identities to equal keys and verify identity order separately. Benchmark optimized builds with realistic input distributions only after correctness checks; a single five-element timing is not evidence that one method is universally fastest.

Sorting is not searching

Linear search can inspect an unsorted array directly. Binary search requires a sorted array in the same order its comparisons assume. Sorting just to do one lookup may cost more than a single linear scan; sorting once can be worthwhile before many searches. Include preprocessing cost in comparisons.

Frequently asked questions

Does in-place mean stable?

No. Selection and heap sort can be in-place but unstable. Insertion sort is both in-place and stable in the linked strict-comparison implementation.

Does an O(n log n) algorithm always beat an O(n²) algorithm?

No. Input size, order, comparison cost and implementation overhead matter. Asymptotic growth is useful for scaling, not a substitute for measuring a real workload.

Are all these algorithms built into C?

No. The linked guides implement them explicitly. qsort is the standard-library sorting interface, with an implementation-chosen algorithm.

Use arrays, functions and the online compiler to try the complete programs. Each guide distinguishes its reference output from a live result.