Stable QuickSort

15 Jun, 2022
A sorting algorithm is said to be stable if it maintains the relative order of records in the case of equality of keys. 
Input : (1, 5), (3, 2) (1, 2) (5, 4) (6, 4) We need to sort key-value pairs in the increasing order of keys of first digit There are two possible solution for the two pairs where the key is same i.e. (1, 5) and (1, 2) as shown below: OUTPUT1: (1, 5), (1, 2), (3, 2), (5, 4), (6, 4) OUTPUT2: (1, 2), (1, 5), (3, 2), (5, 4), (6, 4) A stable algorithm produces first output. You can see that (1, 5) comes before (1, 2) in the sorted order, which was the original order i.e. in the given input, (1, 5) comes before (1, 2).Second output can only be produced by an unstable algorithm. You can see that in the second output, the (1, 2) comes before (1, 5) which was not the case in the original input.
Some sorting algorithms are stable by nature like Insertion sort, Merge Sort, Bubble Sort, etc. And some sorting algorithms are not, like Heap Sort, Quick Sort, etc. QuickSort is an unstable algorithm because we do swapping of elements according to pivot’s position (without considering their original positions).How to make QuickSort stable? 
Quicksort can be stable but it typically isn’t implemented that way. Making it stable either requires order N storage (as in a naive implementation) or a bit of extra logic for an in-place version. In below implementation, we use extra space. The idea is to make two separate lists: 1) First list contains items smaller than pivot. 2) Second list contains items greater than pivot. 
C++
Java
Python3
// C++ code to implement Stable QuickSort.// The code uses middle element as pivot.#include <bits/stdc++.h>using namespace std;     vector<int> quickSort(vector<int> ar)    {             // Base case        if(ar.size() <= 1)        {            return ar;        }        else        {                     // Let us choose middle element a pivot                       int mid = ar.size() / 2;            int pivat = ar[mid];                     // key element is used to break the array            // into 2 halves according to their values            vector<int> smaller ;            vector<int> greater ;                         // Put greater elements in greater list,        // smaller elements in smaller list. Also,        // compare positions to decide where to put.               for(int ind = 0; ind < ar.size(); ind++)        {            int val = ar[ind];            if( ind != mid )            {                if( val < pivat )                {                    smaller.push_back(val);                }                else if(val > pivat)                {                    greater.push_back(val);                }                else                {                                         // If value is same, then considering                    // position to decide the list.                                   if(ind < mid)                    {                        smaller.push_back(val);                    }                    else                    {                        greater.push_back(val);                    }                }            }        }                     vector<int> ans;                   vector<int> sa1 = quickSort(smaller);        vector<int> sa2 = quickSort(greater);                     // add all elements of smaller list into ans list        for(int val1 : sa1)                ans.push_back(val1);                         // add pivat element into ans list        ans.push_back(pivat);                     // add all elements of greater list into ans list        for(int val2 : sa2)                ans.push_back(val2);                     // return ans list        return ans;               }    }         // Driver code    int main()    {           int ar[] = {10, 7, 8, 9, 1, 5};        vector<int> al;        al.push_back(10);        al.push_back(7);        al.push_back(8);        al.push_back(9);        al.push_back(1);        al.push_back(5);           vector<int> sortedAr = quickSort(al);                 for(int x:sortedAr)        cout<<x<<" ";    } // This code is contributed by Pushpesh Raj
// Java code to implement Stable QuickSort.// The code uses middle element as pivot.import java.util.*;class GFG{    public static ArrayList<Integer> quickSort(ArrayList<Integer> ar)    {               // Base case        if(ar.size() <= 1)        {            return ar;        }        else        {                       // Let us choose middle element a pivot                        int mid = ar.size() / 2;            int pivat = ar.get(mid);                        // key element is used to break the array            // into 2 halves according to their values            ArrayList<Integer> smaller = new ArrayList<>();            ArrayList<Integer> greater = new ArrayList<>();                         // Put greater elements in greater list,           // smaller elements in smaller list. Also,           // compare positions to decide where to put.                   for(int ind = 0; ind < ar.size(); ind++)           {               int val = ar.get(ind);               if( ind != mid )               {                   if( val < pivat )                   {                       smaller.add(val);                   }                   else if(val > pivat)                   {                       greater.add(val);                   }                   else                   {                                             // If value is same, then considering                       // position to decide the list.                                          if(ind < mid)                       {                           smaller.add(val);                       }                       else                       {                           greater.add(val);                       }                   }               }           }                       ArrayList<Integer> ans = new ArrayList<Integer>();                         ArrayList<Integer> sa1 = quickSort(smaller);           ArrayList<Integer> sa2 = quickSort(greater);                       // add all elements of smaller list into ans list           for(Integer val1 : sa1)                ans.add(val1);                            // add pivat element into ans list              ans.add(pivat);                       // add all elements of greater list into ans list           for(Integer val2 : sa2)                ans.add(val2);                       // return ans list           return ans;                }    }         // Driver code     public static void main(String args[])    {              int ar[] = {10, 7, 8, 9, 1, 5};        ArrayList<Integer> al = new ArrayList<>();        al.add(10);        al.add(7);        al.add(8);        al.add(9);        al.add(1);        al.add(5);               ArrayList<Integer> sortedAr = quickSort(al);        System.out.println(sortedAr);    }} // This code is contributed by Naresh Saharan
# Python code to implement Stable QuickSort.# The code uses middle element as pivot.def quickSort(ar):          # Base case    if len(ar) <= 1:        return ar     # Let us choose middle element a pivot    else:        mid = len(ar)//2        pivot = ar[mid]         # key element is used to break the array        # into 2 halves according to their values        smaller,greater = [],[]          # Put greater elements in greater list,        # smaller elements in smaller list. Also,        # compare positions to decide where to put.        for indx, val in enumerate(ar):            if indx != mid:                if val < pivot:                    smaller.append(val)                elif val > pivot:                    greater.append(val)                 # If value is same, then considering                # position to decide the list.                else:                    if indx < mid:                        smaller.append(val)                    else:                        greater.append(val)        return quickSort(smaller)+[pivot]+quickSort(greater)     # Driver code to test abovear = [10, 7, 8, 9, 1, 5]sortedAr = quickSort(ar)print(sortedAr)
[1, 5, 7, 8, 9, 10]
In above code, we have intentionally used middle element as pivot to demonstrate how to consider position as part of comparison. Code simplifies a lot if we use last element as pivot. In case of last element, we can always push equal elements in the smaller list. 
AgamKashyap
naresh_saharan151
pushpeshrajdx01
Picked
Quick Sort
Arrays
Sorting
Arrays
Sorting
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Introduction to Data Structures
Window Sliding Technique
Search, insert and delete in an unsorted array
What is Data Structure: Types, Classifications and Applications
Chocolate Distribution Problem
Merge Sort
Bubble Sort Algorithm
QuickSort
Insertion Sort
Selection Sort Algorithm