Loading

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

 

posted @ 2017-12-13 15:33  xpang0  阅读(1322)  评论(1编辑  收藏  举报