📜  稳定的QuickSort

📅  最后修改于: 2021-05-07 05:02:09             🧑  作者: Mango

如果排序算法在键相等的情况下保持记录的相对顺序,则称其为稳定算法。

有些排序算法本质上是稳定的,例如插入排序,合并排序,冒泡排序等。而有些排序算法则不是稳定的,例如堆排序,快速排序等。
QuickSort是一种不稳定的算法,因为我们根据枢轴的位置(不考虑其原始位置)进行元素交换。
如何使QuickSort稳定?

Quicksort可能很稳定,但通常不是那样实现的。要使其稳定,要么需要N阶存储(如在朴素的实现中那样),要么就地版本需要一些额外的逻辑。
在下面的实现中,我们使用额外的空间。这个想法是制作两个单独的列表:
1)第一个列表包含小于数据透视表的项目。
2)第二个列表包含大于枢轴的项目。

Java
// Java code to implement Stable QuickSort.
// The code uses middle element as pivot.
import java.util.*;
class GFG
{
    public static ArrayList quickSort(ArrayList 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 smaller = new ArrayList<>();
            ArrayList 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 ans = new ArrayList();              
           ArrayList sa1 = quickSort(smaller);
           ArrayList 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 al = new ArrayList<>();
        al.add(10);
        al.add(7);
        al.add(8);
        al.add(9);
        al.add(1);
        al.add(5);       
        ArrayList sortedAr = quickSort(al);
        System.out.println(sortedAr);
    }
}
 
// This code is contributed by Naresh Saharan


Python3
# 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 above
ar = [10, 7, 8, 9, 1, 5]
sortedAr = quickSort(ar)
print(sortedAr)


输出
[1, 5, 7, 8, 9, 10]

在上面的代码中,我们有意使用中间元素作为枢轴,以演示如何考虑位置作为比较的一部分。如果我们将last元素用作数据透视表,则代码将大大简化。对于最后一个元素,我们总是可以在较小的列表中放入相等的元素。