- What is quick sort and how it works
- How to implement quick sort in C using recursion
- How quick sort uses the divide-and-conquer strategy with a pivot element
- Step-by-step explanation of the program
- Time and space complexity of quick sort
- Practice exercises to test your understanding
Introduction
In this tutorial, we will learn how to write a C program to sort an array using the quick sort algorithm.
Quick sort is a highly efficient, comparison-based sorting algorithm that follows the divide-and-conquer paradigm. It works by selecting a pivot element from the array and partitioning the other elements into two sub-arraysβthose less than the pivot and those greater than the pivot. The sub-arrays are then recursively sorted.
π‘ Key Point: Quick sort is one of the fastest sorting algorithms in practice, with an average time complexity of O(n log n). It is widely used in real-world applications and is the default sorting algorithm in many programming languages.
Quick sort is used in various real-world applications, such as:
- General-purpose Sorting: Default sorting algorithm in C's
qsort()and C++'sstd::sort - Large Datasets: Efficiently sorts large arrays with good average-case performance
- In-place Sorting: Requires minimal extra memory
- Embedded Systems: Used when memory is limited
Visual Example
Let's see how quick sort sorts the array [10, 7, 8, 9, 1, 5]:
Step 1: Choose pivot (last element: 5)
[10, 7, 8, 9, 1, 5] β Partition around pivot 5 [1, 5, 8, 9, 10, 7] β 5 is in correct position
Step 2: Recursively sort left subarray [1] and right subarray [8, 9, 10, 7]
[1] is already sorted [8, 9, 10, 7] β Choose pivot 7 β Partition β [7, 9, 10, 8]
Step 3: Recursively sort right subarray [9, 10, 8]
[9, 10, 8] β Choose pivot 8 β Partition β [8, 10, 9] [10, 9] β Choose pivot 9 β Partition β [9, 10]
Final Sorted Array: [1, 5, 7, 8, 9, 10]
C Program for Quick Sort
#include <stdio.h>
// Function to swap two elements
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// Partition function - places pivot in correct position
int partition(int arr[], int low, int high) {
// Choose the rightmost element as pivot
int pivot = arr[high];
int i = (low - 1); // Index of smaller element
for(int j = low; j <= high - 1; j++) {
// If current element is smaller than or equal to pivot
if(arr[j] <= pivot) {
i++; // Increment index of smaller element
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
// Quick Sort function
void quickSort(int arr[], int low, int high) {
if(low < high) {
// pi is partitioning index, arr[pi] is now at correct position
int pi = partition(arr, low, high);
// Recursively sort elements before and after partition
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
int main() {
int n, i;
// Ask user for number of elements
printf("Enter the number of elements: ");
scanf("%d", &n);
// Declare array
int arr[n];
// Read elements into the array
printf("Enter %d elements:\n", n);
for(i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// Perform quick sort
quickSort(arr, 0, n - 1);
// Display sorted array
printf("\nSorted array in ascending order: ");
for(i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
Sample Output
Enter the number of elements: 6 Enter 6 elements: 10 7 8 9 1 5 Sorted array in ascending order: 1 5 7 8 9 10
Another Example:
Enter the number of elements: 8 Enter 8 elements: 64 34 25 12 22 11 90 5 Sorted array in ascending order: 5 11 12 22 25 34 64 90
Example with Negative Numbers:
Enter the number of elements: 6 Enter 6 elements: -5 10 -2 8 0 -10 Sorted array in ascending order: -10 -5 -2 0 8 10
Program Explanation
Let's break down the code step by step:
- Include Header File:
#include <stdio.h>includes the standard input/output library. - swap() Function:
- Swaps two integer values using pointers
- Used during the partitioning process
- partition() Function:
- Selects the last element as the pivot
- Places all elements smaller than the pivot to the left
- Places all elements greater than the pivot to the right
- Returns the final position of the pivot
- quickSort() Function:
- Recursively sorts the array
- Partitions the array and recursively sorts the left and right subarrays
- main() Function:
- Gets user input for the array
- Calls
quickSort(arr, 0, n-1)to sort the array - Prints the sorted array
π Note: Quick sort has an average time complexity of O(n log n) and is considered one of the fastest sorting algorithms in practice.
Quick Sort Algorithm
Step-by-step algorithm:
- Start
- Read the array elements
- If
low < high:- Choose a pivot element (typically the last element)
- Partition the array around the pivot
- Recursively sort the left subarray:
quickSort(arr, low, pi - 1) - Recursively sort the right subarray:
quickSort(arr, pi + 1, high)
- Print the sorted array
- End
Time and Space Complexity
| Scenario | Time Complexity | Space Complexity |
|---|---|---|
| Best Case (Balanced Partition) | O(n log n) | O(log n) |
| Worst Case (Already Sorted or Reverse Sorted) | O(nΒ²) | O(n) |
| Average Case | O(n log n) | O(log n) |
π‘ Note: Quick sort is an in-place sorting algorithm, requiring only O(log n) extra space for the recursion stack in the average case.
π» Practice Exercise
Challenge 1: Modify the quick sort program to sort the array in descending order.
Challenge 2: Implement quick sort using a different pivot selection strategy (e.g., middle element, first element, or random pivot).
π Click to Show Solution for Challenge 1
// Change the comparison in the partition function
if(arr[j] >= pivot) { // Change <= to >= for descending
i++;
swap(&arr[i], &arr[j]);
}
Frequently Asked Questions
1. What is quick sort in C?
Quick sort is a divide-and-conquer sorting algorithm that selects a pivot element, partitions the array around it, and recursively sorts the subarrays.
2. What is the time complexity of quick sort?
Quick sort has a time complexity of O(n log n) in the average and best cases, and O(nΒ²) in the worst case (when the pivot is the smallest or largest element).
3. Is quick sort stable?
No, quick sort is not stable because it swaps elements that are not necessarily adjacent, which can change the relative order of equal elements.
4. How can the worst-case performance of quick sort be improved?
The worst-case performance can be improved by using a randomized pivot selection or by using the median-of-three pivot selection strategy.
5. When should I use quick sort?
Quick sort is ideal for large datasets where average-case performance is important. It's the default sorting algorithm in many standard libraries due to its efficiency and in-place nature.
π‘ Tip: Quick sort is one of the most important sorting algorithms to learn. Its divide-and-conquer approach is used in many other algorithms like Binary Search and Merge Sort.