快排算法的实现

先来说网上流行最多的实现,用两个指针,一个从前往后,一个从后往前。直接上代码,如下。

 1 package com.jeaven;
 2 
 3 public class Solution2 {
 4     public void quick_sort(int[] arr, int begin, int end) {
 5         if(begin < end) {
 6             int mid = partition(arr, begin, end);
 7             quick_sort(arr, begin, mid-1);
 8             quick_sort(arr, mid+1, end);
 9         }
10     }
11     
12     
13     /* 双向指针的快排思路
14      * 前一个指针指向开始元素begin,第二个指针指向数组倒数第二个end-1,最后一个元素为轴pivot
15      *当arr[i] > pivot时,交换arr[i]和arr[j]然后 j=j-1
16      *当arr[i] < pivot时,就i++
17      *最终当i和j重合的时候相遇,再将轴归位返回轴的位置,注意下标即可
18     */
19     public int partition(int[] arr, int begin, int end) {
20         int pivot = arr[end];
21         int i = begin;
22         int j = end - 1;
23         while(i < j) {
24             if(arr[i] > pivot) {
25                 int temp = arr[j]; 
26                 arr[j] = arr[i];
27                 arr[i] = temp;
28                 j--;
29             } else {
30                 i++;
31             }
32         }
33         int temp = arr[j+1];
34         arr[j+1] = arr[end];
35         arr[end] = temp;
36         return j+1;
37     }
38     
39     public static void main(String[] args) {
40         int[] arr = {1,4,2,3,5};
41         new Solution2().quick_sort(arr, 0, arr.length-1);
42         for(int c : arr) {
43             System.out.print(c + " ");
44         }
45     }
46 }

再来说说我最喜欢的风格,也是算法导论上的快排实现方法,两个指针从同一边开始,算法导论的思路很清晰,还给出了完整的理论推导,不变性的证明,有兴趣的可以去看看算法道路的快排章节。

下面是算法导论关于快排的实现思路,如下:

 

 然后我给出java版本的快排实现:

 1 package com.jeaven;
 2 
 3 public class Solution3 {
 4     public void quick_sort(int[] arr, int begin, int end) {
 5         if(begin < end) {
 6             int mid = partition(arr, begin, end);
 7             quick_sort(arr, begin, mid-1);
 8             quick_sort(arr, mid+1, end);
 9         }
10     }
11     
12     public int partition(int[] arr, int begin, int end) {
13         int pivot = arr[end];
14         int i = begin - 1;
15         for(int j = begin; j < end; j++) {
16             if(arr[j] < pivot) {
17                 i++;
18                 int temp = arr[j];
19                 arr[j] = arr[i];
20                 arr[i] = temp;
21             }
22         }
23         int temp = arr[i+1];
24         arr[i+1] = arr[end];
25         arr[end] = temp;
26         return i+1;
27     }
28     
29     public static void main(String[] args) {
30         int[] arr = {1,4,2,3,5};
31         new Solution3().quick_sort(arr, 0, arr.length-1);
32         for(int c : arr) {
33             System.out.print(c + " ");
34         }
35     }
36 }

 

说明:我喜欢选最后一个元素为轴pivot,当然可以选取数组任意位置为轴,即使分的恨不均匀,但是可以证明除了极端情况,时间复杂度仍然为O(nlgn)。如果选取其他位置作为轴,代码实现的时候可以先将轴和最后一个元素交换位置,这样就可以看成是最后一个位置是轴,就可以很容易实现。

posted @ 2019-10-21 11:07  jeavenwong  阅读(596)  评论(0编辑  收藏  举报