Back to Benchmark

Quick Sort - O(n log n) Complexity

Understanding how quicksort achieves linearithmic time through divide and conquer

What is Quick Sort?

Quick Sort is a divide-and-conquer sorting algorithm that works by selecting a "pivot" element and partitioning the array around it. Elements smaller than the pivot go to the left, and elements larger go to the right. This process is repeated recursively for the subarrays.

Key Characteristics:

  • Divide and Conquer: Breaks problem into smaller subproblems
  • In-Place: Sorts array in place, minimal extra memory
  • Average Case: O(n log n): Very efficient for most inputs
  • Worst Case: O(n²): When pivot is always smallest/largest

Think of it like organizing books on a shelf - pick a book (pivot), put smaller books to the left and larger books to the right, then repeat for each section!

How Does Quick Sort Work?

1. Choose a Pivot

Select an element as the pivot (often the last element). The pivot will be in its final sorted position after partitioning.

2. Partition the Array

Rearrange elements so that all elements smaller than the pivot are to its left, and all elements larger are to its right. The pivot is now in its correct sorted position.

3. Recursively Sort Subarrays

Recursively apply quicksort to the left subarray (elements < pivot) and right subarray (elements > pivot). Base case: subarray with 0 or 1 element is already sorted.

4. Logarithmic Depth

In the average case, the pivot divides the array roughly in half:

Level 0: n elements
Level 1: n/2 + n/2 = n elements
Level 2: n/4 + n/4 + n/4 + n/4 = n elements
...
Level log₂(n): n/2^log₂(n) = 1 element per partition
Total work: n elements × log₂(n) levels = O(n log n)
Interactive Quick Sort Visualization
Watch how quicksort partitions and recursively sorts the array!

Code Example:

// Quick Sort - O(n log n) average case
function quickSort(arr, low, high) {
  if (low < high) {
    // Partition and get pivot index
    const pivotIndex = partition(arr, low, high);

    // Recursively sort left and right subarrays
    quickSort(arr, low, pivotIndex - 1); // Left: < pivot
    quickSort(arr, pivotIndex + 1, high); // Right: > pivot
  }
}

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

  for (let j = low; j < high; j++) {
    if (arr[j] < pivot) {
      i++;
      [arr[i], arr[j]] = [arr[j], arr[i]]; // Swap
    }
  }
  [arr[i + 1], arr[high]] = [arr[high], arr[i + 1]]; // Place pivot
  return i + 1;
}
Built-in Functions for Sorting
Most programming languages provide built-in sorting functions that often use quicksort or similar efficient algorithms:

JavaScript/TypeScript

array.sort() - O(n log n) - In-place sort
// Uses quicksort or similar (implementation-dependent)
array.sort((a, b) => a - b) - O(n log n) - Custom comparator
// Sort numbers: ascending order

Python

sorted(list) - O(n log n) - Returns new sorted list
// Uses Timsort (hybrid of merge sort and insertion sort)
list.sort() - O(n log n) - In-place sort
// Modifies list in place, returns None
sorted(list, key=func) - O(n log n) - Custom key
// Sort by custom function

Java

Arrays.sort(array) - O(n log n) - Dual-pivot quicksort
// java.util.Arrays: uses optimized quicksort variant
Collections.sort(list) - O(n log n) - Timsort
// For List collections
list.sort(Comparator) - O(n log n) - Custom comparator
// Sort with custom comparison logic

C++

std::sort(begin, end) - O(n log n) - Introsort
// std::sort: hybrid of quicksort, heapsort, and insertion sort
std::sort(begin, end, comp) - O(n log n) - Custom comparator
// Sort with custom comparison function
std::qsort() - O(n log n) - C-style quicksort
// C library function, less type-safe
Why is Quick Sort O(n log n)?

1. Logarithmic Recursion Depth

In the average case, the pivot divides the array roughly in half. This creates a balanced binary tree of recursive calls with depth log₂(n). Each level processes all n elements.

2. Linear Work Per Level

At each level of recursion, the partition operation processes elements:

Level 0: Partition n elements → O(n)
Level 1: Partition n/2 + n/2 = n elements → O(n)
Level 2: Partition n/4 × 4 = n elements → O(n)
...
Each level: O(n) work
Total: O(n) × O(log n) levels = O(n log n)

3. Worst Case vs Average Case

Quick sort complexity:

Best case: O(n log n) - Pivot always divides in half
Average case: O(n log n) - Pivot divides roughly in half on average
Worst case: O(n²) - Pivot always smallest/largest (unbalanced)
Most implementations: O(n log n) average

💡 Why O(n log n) is Efficient

O(n log n) is the theoretical lower bound for comparison-based sorting algorithms. Quick sort achieves this in practice and is often faster than other O(n log n) algorithms due to good cache performance and in-place sorting.

Time Complexity Comparison
AlgorithmBestAverageWorstSpace
Quick SortO(n log n)O(n log n)O(n²)O(log n)
Merge SortO(n log n)O(n log n)O(n log n)O(n)
Heap SortO(n log n)O(n log n)O(n log n)O(1)
Bubble SortO(n)O(n²)O(n²)O(1)
Insertion SortO(n)O(n²)O(n²)O(1)
Real-World Examples

📊 Database Sorting

Database systems use quicksort (or variants) to sort query results. When you ORDER BY a column, the database efficiently sorts millions of rows using O(n log n) algorithms.

🎮 Game Leaderboards

Gaming platforms use efficient sorting to maintain leaderboards. Quick sort's O(n log n) performance ensures leaderboards update quickly even with thousands of players.

🛒 E-commerce Sorting

Online stores use sorting to display products by price, rating, or popularity. Quick sort efficiently handles large product catalogs, providing fast sorting for users.

📧 Email Clients

Email applications sort messages by date, sender, or subject. Quick sort's in-place nature and O(n log n) performance make it ideal for sorting large inboxes efficiently.

🔍 Search Results

Search engines sort results by relevance, date, or other criteria. Quick sort efficiently organizes search results, ensuring fast response times for users.

Key Takeaways
  • Quick sort is O(n log n) - linearithmic time

    Average case: divides array in half log₂(n) times, processing n elements per level

  • Divide and conquer strategy

    Breaks problem into smaller subproblems, solves recursively, combines results

  • In-place sorting

    Sorts array in place with O(log n) extra space for recursion stack

  • Worst case can be O(n²)

    When pivot is always smallest/largest, but this is rare with good pivot selection

Practice Exercises
Test your understanding of quicksort with these exercises. Try to solve them yourself before checking the answers!