算法——快速排序迭代式和递归式的Java实现

Posted 乌池鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法——快速排序迭代式和递归式的Java实现相关的知识,希望对你有一定的参考价值。

快速排序迭代式和递归式的Java实现

  快速排序基于分治法的思想,在待排序表中任选一值作为中枢值 pivot,一趟快排将所有大于该值的元素置于一边,小于该值的元素置于另一边,这样一个元素在排序中的最终位置就已确定。接下来将中枢值左右两边的区域分别进行下一趟快排,直到所有的元素都有序排列。

  空间效率:最好情况为 O(log2(n+1)),最坏情况为 O(n),平均空间复杂度 O(log2(n))

  时间效率:最好情况为 O(n*log2(n)),最坏情况 O(n^2),平均时间复杂度 O(n*log2(n))。

  快速排序是所有内部排序中平均性能最优的算法,同时也是一个不稳定的排序算法。

 

归式

 1 public class Test {
 2     
 3     public static void main(String[] args) {
 4         
 5         int[] nums = {2, 12, 32, 32, 43, 5, 74, 13, 87, 12, 44, 2, 41, 5, 33};
 6         
 7         recursiveQuicksort(nums,0,nums.length-1);
 8         
 9         System.out.println("Sorted array : " + Arrays.toString(nums));
10         
11     }
12     
13     //recursiveQuicksort(int[] 被排序数组, int 数组下界, int 数组上界)
14     private static void recursiveQuicksort(int[] nums, int low, int high) {
15         
16         if(low < high){
17             
18             int pivotpos = partition(nums, low, high);
19             
20             recursiveQuicksort(nums, low, pivotpos -1);
21             recursiveQuicksort(nums, pivotpos + 1, high);
22             
23         }
24     }
25 
26     private static int partition(int[] nums, int low, int high) {
27         
28         //将当前列表中第一个元素设为中枢值
29         int pivot = nums[low];  
30         
31         while(low < high){
32             
33             //找到第一个小于中枢值的数,置于low的位置
34             while(low < high && nums[high] >= pivot){
35                 --high;
36             }
37             nums[low] = nums[high];
38 
39             //找到第一个大于中枢值的数,置于high的位置
40             while(low < high && nums[low] <= pivot){
41                 ++low;
42             }
43             nums[high] = nums[low];
44         }
45         
46         //这样一趟下来nums[low]左端都是小于中枢值的数,右端都是大于中枢值的数,一个元素的最终排序位置确定
47         nums[low] = pivot;
48         
49         return low;
50     }
51 }

 

迭代式

  递归的操作更加便于理解,但是递归频繁的调用函数会不断让参数和其它额外的变量入栈,从而造成栈空间的极大浪费,如果调用层次很深,还有可能造成栈溢出,而入栈也会有性能损失。因此迭代式自己模拟入栈的过程从而提高快排的效率。

 1 public class Test {
 2     
 3     public static void main(String[] args) {
 4         
 5         int[] nums = {34, 32, 43, 12, 11, 32, 22, 21, 32};
 6 
 7         System.out.println("Unsorted array : " + Arrays.toString(nums));
 8 
 9         iterativeQuicksort(nums);
10 
11         System.out.println("Sorted array : " + Arrays.toString(nums));
12 
13     }
14 
15     public static void iterativeQuicksort(int[] nums) {
16         
17         //新建栈,模拟递归操作
18         Stack stack = new Stack();
19         
20         stack.push(0);
21         stack.push(nums.length);
22 
23         while (!stack.isEmpty()) {
24             int high = (int)stack.pop();
25             int low = (int)stack.pop();
26 
27             if (high - low < 2) {
28                 continue;
29             }
30             
31             //pivot为low与high的平均值,保证随机性,降低抽到数组中最小值或最大值的概率
32             int p = low + ((high - low) / 2); //pivot为low与high的平均值,这样写防止溢出
33 
34             //经过一趟partition后,p所在的位置已是排序后的最终位置
35             p = partition(nums, p, low, high);
36 
37             stack.push(p + 1);
38             stack.push(high);
39 
40             stack.push(low);
41             stack.push(p);
42         }
43     }
44 
45     private static int partition(int[] input, int position, int start, int end) {
46         
47         int l = start;
48         int h = end - 2;
49         
50         int pivot = input[position];
51 
52         //将pivot换至最右端
53         swap(input, position, end - 1); 
54 
55         //筛选pivot的最终位置
56         while (l < h) {
57             if (input[l] < pivot) {
58                 l++;
59             } else if (input[h] >= pivot) {
60                 h--;
61             } else {
62                 swap(input, l, h);
63             }
64         }
65         //pos为pivot的最终位置
66         int pos = h;
67         
68         //如果pivot左边的数都小于它,说明它本来就应该在最右端的位置,因此pos++
69         if (input[h] < pivot) {
70             pos++;
71         }
72         swap(input, end - 1, pos);
73         
74         return pos;
75     }
76 
77     private static void swap(int[] arr, int i, int j) {
78         int temp = arr[i];
79         arr[i] = arr[j];
80         arr[j] = temp;
81     }
82 }

 

递归与迭代

递归:重复调用函数自身实现循环

  • 优点:

    • 极大的减少了代码量,代码简单易读

    • 将大问题转化成小问题,逻辑清晰

  • 缺点:

    • 递归不断调用函数,不断压栈,浪费空间容易造成栈溢出

    • 频繁的入栈出栈操作也会导致性能损失

 

迭代:函数内某段代码实现循环,不断把变量的原值推导成新值,直到最终结果产生

  • 优点:

    • 效率比递归高,运行时间只随循环的增加而增加

    • 不需要反复调用从而占用栈的空间

  • 缺点:

    • 代码复杂,较难理解

    • 面对复杂问题时,难以构思代码

以上是关于算法——快速排序迭代式和递归式的Java实现的主要内容,如果未能解决你的问题,请参考以下文章

Java快速排序的非递归实现

DNS迭代式和递归式域名查询对比

快速排序Java代码简洁实现

C语言编程实现时间片轮转算法,尽量写得简单易懂,谢谢

排序算法之快速排序(Java)

排序算法之快速排序(Java)