QuickSort using Random Pivoting


Quick Sort is a Divide and Conquer algorithm. In this algorithm, we elect a pivot element and then partition the array around the pivot element. The two partitions are such that one part contains elements all lower than the pivot element and the other part contains elements all higher than the pivot element. Similarly, each part is further partitioned around a pivot selected in each part and this process is executed until one single element is reached.

Choosing a Pivot

A pivot can be chosen in an array as follows −

  • A random pivot.

  • Rightmost or leftmost element as pivot.

  • Median as the pivot.

In this article, we’ll be using the first approach to choose a pivot and implement the quicksort algorithm.

Problem Statement

Given an array. Use the quick sort algorithm using random pivoting to sort the array.

Sample Example 1

Input: [3, 1, 7, 2, 10]
Output: [1, 2, 3, 7, 10]

Explanation − Let, 3 be chosen as the random pivot, swap it with 10 and then set 3 as the pivot and partition the array with 3 as the pivot. After the first partition, the array is [1, 2, 3, 7, 10] with 3 at its sorted position. Then call the function on both the subarrays on the left and right of 3 to sort the rest array.

Sample Example 2

Input: [11, 32, 7, 90, 18, 34]
Output: [7, 11, 18, 32, 34, 90]

Pseudocode

Pseudocode for Swap()

procedure swap (*a, *b)
   temp = *a
   *a = *b
   *b = temp
end procedure

Pseudocode for pickRandom()

procedure pickRandom (arr[], start, end)
   num = Random number between start and end
   swap arr[num] and arr[end]
end procedure

Pseudocode for partition()

procedure partition (arr[], start, end)
   pickRandom (arr, start, end)
   pivot = arr[end]
   i = start
   for k = start to end - 1
      if arr[k] <= pivot
         swap arr[k] and arr[i]
         i = i + 1
      end if
   end for
   swap arr[i] and arr[end]
   return i
end procedure

Pseudocode quickSort()

procedure quickSort (arr[], start, end)
   if start < end
      p = pickRandom (arr[], start, end)
      quickSort (arr[], start, p-1)
      quickSort (arr[], p+1, end)
   end if
end procedure

Working

Let’s take an unsorted array, and call the staaquickSort() function from start to end.

Starting with the pickRandom() function,

Let, num = random number between start and end = 2

Swapping arr[1] and arr[end], we get the following array,

Upon the call of partition() function,

Pivot = arr[end] = 23

Since the pivot is at the end, so algorithm starts from the start and moves towards the end. Taking k from start to end - 1 in a loop and i = start

Now, arr[k] < arr[pivot], so swap arr[k] and arr[i] and i = i + 1.

Now, arr[k] < arr[pivot], so swap arr[k] and arr[i] and i = i + 1.

Now, arr[k] < arr[pivot], so swap arr[k] and arr[i] and i = i + 1.

Now, arr[k] > arr[pivot], so k moves forward.

Now, arr[k] > arr[pivot] and the loop ends.

After the loop ends, swap arr[i] and arr[pivot].

And return i = 3.

Thus, the next quickSort() is called on the array from start to i-1 and then from i+1 to end.

Example: C++ Implementation

In the following program, for sorting an array by quicksort using random pivoting, we first select a random index of the array. The number on this random index is then swapped with the end element of the array. Then the end element is chosen as the pivot. Then the array is partitioned around this pivot and recursively quickSort is called on the partitioned arrays until we are left with one element in each subarray.

#include <bits/stdc++.h>
using namespace std;

// function to swap values of two variables
void swap(int *x, int *y){
   int t = *x;
   *x = *y;
   *y = t;
}

// This function picks a random index between start and end and swaps the value at that index to the value at end index.
void pickRandom(int arr[], int start, int end){
   int num = start + rand() % (end - start + 1);
   swap(arr[num], arr[end]);
}

// This function calls the pickRandom() function and then partitions the array into two subarrays
int partition(int arr[], int start, int end){
   pickRandom(arr, start, end);
   
   // End element is chosen as pivot
   int pivot = arr[end];
   int i = start;
   for (int k = start; k < end; k++){
      if (arr[k] <= pivot){
         swap(arr[k], arr[i]);
         i++;
      }
   }
   swap(arr[i], arr[end]);
   
   // The array is divided into two sub-parts with the left part having all the elements smaller than the pivot and right part having elements bigger than the pivot.
   return i;
}
void quickSort(int arr[], int start, int end){
   if (start < end){
   
      // p is the point of partition
      int p = partition(arr, start, end);
      
      // Calling quicksort on left subarray
      quickSort(arr, start, p - 1);
      
      // Calling quicksort on right subarray
      quickSort(arr, p + 1, end);
   }
}
int main(){
   int arr[6] = {19, 4, 23, 77, 31, 8};
   
   // Before Sorting
   cout << "Array before sorting : ";
   for (int i = 0; i < 6; i++){
      cout << arr[i] << "  ";
   }
   
   // Applying quick Sort
   quickSort(arr, 0, 5);
   
   // After Sorting
   cout << "\nArray after sorting : ";
   for (int i = 0; i < 6; i++){
      cout << arr[i] << "  ";
   }
   return 0;
}

Output

Array before sorting : 19  4  23  77  31  8  
Array after sorting : 4  8  19  23  31  77 

Time Complexity − Worst Case Complexity = O(n2)

Average(Expected) Case Complexity = O(nlogn).

Space Complexity − O(nlogn) due to the recursive stack space used.

Conclusion

In conclusion, using quick sort with random pivoting for sorting an array helps improve the average or expected time complexity by O(nlogn) but the worst-case complexity remains O(n2).

Updated on: 04-Sep-2023

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements