Quicksort in Java

Quicksort is a divide and conquer algorithm. It works by breaking an array into two sub-arrays and then recursively sort the sub-arrays.

Steps for QuickSort

  1. Select the pivot element.  Any element that you choose would be called the pivot element.
  2. All the elements that are smaller than the pivot element are kept in one array and all the elements that are larger than the pivot element are placed in another array.
  3. Now recursively repeat from step 1 on both the sub-arrays separately until the sub-array has no more elements or 1 element. Array with 1 element is already sorted.

Quicksort Example

In this example we sort an array with contents { 7, 5, 6, 8, 4, 3, 2, 1, 9 }. The below image explains how the quick sort works.

quicksort example
Quicksort example

 

Quicksort Java implementation

Here is a java implementation. I have added a lot of logging so that from the output all the steps become clear.
package com.programtak.quicksort.example;

import java.util.Arrays;

public class QuickSort {
 public static void main(String[] args) {
  int[] array4Sorting = { 7, 5, 6, 8, 4, 3, 2, 1, 9 };
  System.out.println("Initial array: " + Arrays.toString(array4Sorting));

  // leftIndex is 0 and rightIndex is array4Sorting.length - 1;
  new QuickSort().quickSort(array4Sorting, 0, array4Sorting.length - 1);
  System.out.println("Sorted array: " + Arrays.toString(array4Sorting));
 }

 /**
  * 
  * @param array4Sorting-
  *            array to be sorted
  * @param l
  *            - left index
  * @param r
  *            - right index
  */
 public void quickSort(int[] array4Sorting, int l, int r) {
  
  if (array4Sorting == null || array4Sorting.length == 0){
   return;
  }
  
  if (l >= r) {
   return;
  }

  // choose the pivot, we select the middle of array
  int pivotLocation = (r + l) / 2;
  int pivot = array4Sorting[pivotLocation];
  System.out.println("Pivot:" + pivot);
  // make left < pivot and right > pivot
  int left = l, right = r;
  while (left <= right) {

   while (array4Sorting[left] < pivot) {
    System.out.print("Since " + array4Sorting[left] + " < " + pivot);
    left++;
    System.out.println(", Move left pointer to element: " + array4Sorting[left]);
   }

   while (array4Sorting[right] > pivot) {
    System.out.print("Since " + array4Sorting[right] + " > " + pivot);
    right--;
    System.out.println(", Move right pointer to element: " + array4Sorting[right]);
   }
   /*
    * Swap the left and right elements recursively
    * 
    */
   if (left <= right) {
    swapElements(array4Sorting, left, right);
    left++;
    System.out.print(", Move left pointer to element: " + array4Sorting[left]);
    right--;
    System.out.println(", Move right pointer to element: " + array4Sorting[right]);
   }
  }

  System.out.println("Array after current recursion:" + Arrays.toString(array4Sorting) + "n");
  // sort the sub-arrays recursively
  if (l < right) {
   System.out.println("Sub-Array to sort:" + Arrays.toString(Arrays.copyOfRange(array4Sorting, l, right)));
   quickSort(array4Sorting, l, right - 1);
  }

  if (r > left) {
   System.out.println("Sub-Array to sort:" + Arrays.toString(Arrays.copyOfRange(array4Sorting, left, r + 1)));
   quickSort(array4Sorting, left, r);
  }
 }

 private void swapElements(int[] array4Sorting, int left, int right) {
  System.out.print("Swapping: " + array4Sorting[left] + " with: " + array4Sorting[right]);
  int temp = array4Sorting[left];
  array4Sorting[left] = array4Sorting[right];
  array4Sorting[right] = temp;
 }

}
output:
 Initial array: [7, 5, 6, 8, 4, 3, 2, 1, 9]
Pivot:4
Since 9 > 4, Move right pointer to element: 1
Swapping: 7 with: 1, Move left pointer to element: 5, Move right pointer to element: 2
Swapping: 5 with: 2, Move left pointer to element: 6, Move right pointer to element: 3
Swapping: 6 with: 3, Move left pointer to element: 8, Move right pointer to element: 4
Swapping: 8 with: 4, Move left pointer to element: 8, Move right pointer to element: 4
Array after current recursion:[1, 2, 3, 4, 8, 6, 5, 7, 9]

Sub-Array to sort:[1, 2, 3]
Pivot:2
Since 1 < 2, Move left pointer to element: 2
Since 3 > 2, Move right pointer to element: 2
Swapping: 2 with: 2, Move left pointer to element: 3, Move right pointer to element: 1
Array after current recursion:[1, 2, 3, 4, 8, 6, 5, 7, 9]

Sub-Array to sort:[8, 6, 5, 7, 9]
Pivot:5
Since 9 > 5, Move right pointer to element: 7
Since 7 > 5, Move right pointer to element: 5
Swapping: 8 with: 5, Move left pointer to element: 6, Move right pointer to element: 6
Since 6 > 5, Move right pointer to element: 5
Array after current recursion:[1, 2, 3, 4, 5, 6, 8, 7, 9]

Sub-Array to sort:[6, 8, 7, 9]
Pivot:8
Since 6 < 8, Move left pointer to element: 8
Since 9 > 8, Move right pointer to element: 7
Swapping: 8 with: 7, Move left pointer to element: 8, Move right pointer to element: 7
Array after current recursion:[1, 2, 3, 4, 5, 6, 7, 8, 9]

Sub-Array to sort:[6]
Sub-Array to sort:[8, 9]
Pivot:8
Since 9 > 8, Move right pointer to element: 8
Swapping: 8 with: 8, Move left pointer to element: 9, Move right pointer to element: 7
Array after current recursion:[1, 2, 3, 4, 5, 6, 7, 8, 9]

Sorted array: [1, 2, 3, 4, 5, 6, 7, 8, 9]

QuickSort Complexity

In worst case scenario the pivot divides the n sized list repeatedly in each recursion into two sub-lists of sizes 0 and n − 1. Worst-case performance of quicksort is O(n²) time.

The best case scenario occurs when a list is divided into two almost equal sub-lists repeatedly in each recursion. Best-case performance of quicksort is O(n log n) time.

Average case performance of quicksort is O(n log n)

Like this post? Don’t forget to share it!