JAVA數據結構--快速排序


快排概念

快速排序英語:Quicksort),又稱划分交換排序partition-exchange sort),一種排序算法,最早由東尼·霍爾提出。在平均狀況下,排序n個項目要{\displaystyle O(n\log n)}(大O符號)次比較。在最壞狀況下則需要O(n^{2})次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他{\displaystyle O(n\log n)}算法更快,因為它的內部循環(inner loop)可以在大部分的架構上很有效率地被實現出來。

實現思想

快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分為兩個子序列(sub-lists)。

步驟為:

  1. 從數列中挑出一個元素,稱為"基准"(pivot),
  2. 重新排序數列,所有比基准值小的元素擺放在基准前面,所有比基准值大的元素擺在基准后面(相同的數可以到任何一邊)。在這個分區結束之后,該基准就處於數列的中間位置。這個稱為分區(partition)操作。
  3. 遞歸地(recursively)把小於基准值元素的子數列和大於基准值元素的子數列排序。

遞歸到最底部時,數列的大小是零或一,也就是已經排序好了。這個算法一定會結束,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它最后的位置去。

借用下啊哈算法的圖:

094811yilrz1tkzkvlrriz.png

i和j分別為左哨兵和右哨兵,這里樞紐元定為6,然后分別從左往右(i++)和右往左(j--)開始遍歷

左哨兵查找比6大的元素,右哨兵查找比6小的元素

第一次交換結果

095430axy0qkhxxkktkktk.png

095437kdandfxhbtokk2qh.png

 

第二次交換結果

095448k1kevwlz41373e7k.png

095458ejza15wscjv7iw5c.png

 

095506uz7e1uuukcblhkxv.png

相遇后直接與樞紐元交換

095514cag5fumuqqg5jnsw.png

095530e0jf6p0y6aaaw2ir.png

然后再遞歸排序就行

232129ogop8gk0r8y7l70k.png

 


快排核心算法代碼

 1 public static <T extends Comparable<? super T>> void quicksort(T[] a,int left,int right) {
 2         /*
 3          * 當數組不小於3時,才推薦使用快排
 4          * */
 5         if(left+CUTOFF<=right)
 6         {
 7             //取出樞紐元,樞紐元的位置為right-1
 8             T privot=median3(a, left, right);
 9             
10             int i=left,j=right-1;
11             for(;;)
12             {
13                 while(a[++i].compareTo(privot)<0) {}//i哨兵向右遍歷
14                 while(a[--j].compareTo(privot)>0) {}//j哨兵向左遍歷
15                 if(i<j)
16                     swapReferences(a, i, j);
17                 else
18                     break;
19             }
20             /*
21              * for循環終止條件為i和j相遇,此時再將樞紐元歸位
22              * */
23             swapReferences(a, i, right-1);
24             
25             quicksort(a, left, i-1);//對左半部進行遞歸
26             quicksort(a, i+1, right);//對右半部進行遞歸
27         }
28         else
29         {}
30     }

全部代碼實現

 1 public class MyQuickSort {
 2     private static final int CUTOFF=3;
 3     public static <T extends Comparable<? super T>> void quicksort(T[] a) {
 4         quicksort(a,0,a.length-1);
 5     }
 6     public static <T extends Comparable<? super T>> void quicksort(T[] a,int left,int right) {
 7         /*
 8          * 當數組不小於3時,才推薦使用快排
 9          * */
10         if(left+CUTOFF<=right)
11         {
12             //取出樞紐元,樞紐元的位置為right-1
13             T privot=median3(a, left, right);
14             
15             int i=left,j=right-1;
16             for(;;)
17             {
18                 while(a[++i].compareTo(privot)<0) {}//i哨兵向右遍歷
19                 while(a[--j].compareTo(privot)>0) {}//j哨兵向左遍歷
20                 if(i<j)
21                     swapReferences(a, i, j);
22                 else
23                     break;
24             }
25             /*
26              * for循環終止條件為i和j相遇,此時再將樞紐元歸位
27              * */
28             swapReferences(a, i, right-1);
29             
30             quicksort(a, left, i-1);//對左半部進行遞歸
31             quicksort(a, i+1, right);//對右半部進行遞歸
32         }
33         else
34         {}
35     }
36     /*
37      * 數組中數值交換
38      * */
39     public static <T> void swapReferences(T[] a,int index1,int index2) {
40         T tmp=a[index1];
41         a[index1]=a[index2];
42         a[index2]=tmp;
43     }
44     /*
45      * 確定樞紐元,樞紐元的位置放在right-1位置
46      * */
47     private static <T extends Comparable<? super T>> T median3(T[] a,int left,int right) {
48         int center=(left+right)/2;
49         if(a[center].compareTo(a[left])<0)
50             swapReferences(a, left, center);
51         if(a[right].compareTo(a[center])<0)
52             swapReferences(a, center, right);
53         if(a[right].compareTo(a[left])<0)
54             swapReferences(a, left, right);
55         
56         swapReferences(a, center, right-1);
57         return a[right-1];
58     }
59 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM