Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Quick sort, usually written as quicksort, is a divide-and-conquer sorting algorithm: it selects a pivot, partitions an array around that value, then recursively sorts the resulting subranges. A hand-written version gives you control over those steps; C’s qsort() library function provides a general sorting interface, but the C and POSIX specifications do not require it to use quicksort internally.

How quicksort sorts an array

Quicksort works on a range of elements. It chooses one element as a pivot, rearranges the range so values that compare lower are on one side and higher values are on the other, and places the pivot in its final sorted position. It then applies the same process to the two ranges on either side. The process stops when a range has zero or one element, since such a range is already sorted. MIT’s 6.087 Practical Programming in C lecture presents this recursive structure and relates it to C’s qsort() facility: MIT 6.087 lecture material.

For example, partitioning [8, 3, 6, 2] around pivot 2 places 2 before the larger values. The algorithm then sorts the remaining range. The exact intermediate order depends on the pivot and partition method.

A simple recursive quicksort in C

This teaching example sorts integers in place. Its range endpoints are inclusive, so call it with lo = 0 and hi = count - 1 for a nonempty array.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
Introduction to Algorithms, fourth edition
  • color: White
  • INTRODUCTION TO ALGORITHMS, FOURTH EDITION
#include <stddef.h>

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

static int partition(int a[], int lo, int hi) {
    int pivot = a[hi];
    int i = lo;
    for (int j = lo; j < hi; ++j) {
        if (a[j] <= pivot) {
            swap_int(&a[i], &a[j]);
            ++i;
        }
    }
    swap_int(&a[i], &a[hi]);
    return i;
}

void quicksort_int(int a[], int lo, int hi) {
    if (lo >= hi) return;
    int p = partition(a, lo, hi);
    quicksort_int(a, lo, p - 1);
    quicksort_int(a, p + 1, hi);
}

What the partition function guarantees

Before each loop iteration, elements in the processed portion that compare less than or equal to the pivot are kept to the left; the remaining processed elements are greater. At the end, the pivot is swapped into index i. The function returns that index, so the recursive calls exclude the pivot itself.

Calling it safely

For an array with count elements, avoid computing count - 1 when the array is empty. One straightforward call-site check is:

if (count > 0) {
    quicksort_int(values, 0, count - 1);
}

This implementation is intentionally basic: it always selects the last element as pivot. That makes the code easy to follow, but input patterns and many duplicate values can lead to highly unbalanced partitions and deep recursion. For production use, consider pivot strategy, recursion depth, duplicate-heavy or adversarial inputs, and whether the library routine better suits the requirement.

How fast is quicksort?

When partitions are reasonably balanced, quicksort’s average running time is O(n log n). When each pivot leaves one large subrange and one tiny subrange, the worst case is O(n²). These are properties of the algorithm; they are not performance guarantees for the C qsort() interface. A detailed analysis of quicksort reports these bounds: arXiv, “A Detailed Analysis of Quicksort Running Time”.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
Sale
Algorithm Design
  • Used Book in Good Condition

How to use C’s qsort()

For general-purpose sorting, C provides qsort() through <stdlib.h>. You supply the array’s base address, the number of elements, each element’s size in bytes, and a comparator.

#include <stdlib.h>

static int cmp_int(const void *pa, const void *pb) {
    int a = *(const int *)pa;
    int b = *(const int *)pb;
    return (a > b) - (a < b);
}

/* Sort count integers in values. */
qsort(values, count, sizeof values[0], cmp_int);

The comparator returns a negative value when the first element should come before the second, zero when they compare equal, and a positive value when the first should come after the second. It must provide consistent ordering and must not modify the array. The Open Group specifies the array-sorting interface in its POSIX qsort() reference; Microsoft also documents its C runtime comparator interface at Microsoft Learn: qsort.

Hand-written quicksort or qsort()?

Consideration Hand-written quicksort qsort()
Control You choose pivot handling, partitioning, data type, and recursion safeguards. You provide an element comparator; internal sorting strategy is implementation-defined and not specified by the interface.
Types and comparison A specialized integer function can compare values directly. The comparator receives generic pointers and must interpret the element type.
Performance claims The usual quicksort average and worst-case bounds apply to the algorithm and its pivot behavior. C and POSIX do not promise a complexity bound; avoid claiming it is quicksort unless you have verified the specific library and version.
Equal elements Stability depends on how your implementation is written. Equal elements have unspecified relative order; qsort() is not a stable-sort interface.
Portability Your implementation and its assumptions are your responsibility. The standard C sorting interface is portable, though implementation details and performance can differ.

For a portable comparator-based sort, qsort() is often the direct choice. Write a custom algorithm when you need specific control, are learning partitioning, or have requirements the library interface does not address. If equal elements must retain their original order, neither the name nor interface of qsort() provides that guarantee.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Is qsort() actually quicksort?

Not necessarily. The name is historical, not a promise about the algorithm used by every C library. POSIX specifies what the function must do—“The qsort() function shall sort an array of nel objects”—but not which sorting algorithm it must use. Microsoft’s C runtime documentation says its qsort function implements a quick-sort algorithm, but that is a statement about Microsoft’s implementation, not a universal C guarantee. See the Open Group specification and Microsoft documentation.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Quick Recap

SaleBestseller No. 1
Introduction to Algorithms, fourth edition
Introduction to Algorithms, fourth edition
color: White; INTRODUCTION TO ALGORITHMS, FOURTH EDITION
$91.50
SaleBestseller No. 2
SaleBestseller No. 3
Algorithm Design
Algorithm Design
Used Book in Good Condition
$224.59
Bestseller No. 4

Common mistakes to avoid

  • Using a subtraction comparator: returning *(int *)pa - *(int *)pb can overflow for extreme integer values. The relational comparison pattern in the example avoids that subtraction.
  • Getting the recursive ranges wrong: once partition returns p, recurse on lo..p-1 and p+1..hi, not on ranges that include the pivot again.
  • Assuming stability: qsort() does not specify the relative order of equal elements.
  • Assuming the library’s name guarantees its internals: the standard interface does not promise quicksort, a time bound, or a particular pivot policy.
  • Ignoring the empty-array case: guard the call before forming an inclusive upper index such as count - 1.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.