今天给大家带来的是:Java快速排序的两种实现方式,一种是基于递归的方式,一种是基于非递归的方式。
快速排序的递归实现的算法思想:基于分治的思想,是冒泡排序的改进型。首先在数组中选择一个基准点(该基准点的选取可能影响快速排序的效率,后面讲解选取的方法),然后分别从数组的两端扫描数组,设两个指示标志(lo指向起始位置,hi指向末尾),首先从后半部分开始,如果发现有元素比该基准点的值小,就交换lo和hi位置的值,然后从前半部分开始扫秒,发现有元素大于基准点的值,就交换lo和hi位置的值,如此往复循环,直到lo>=hi,然后把基准点的值放到hi这个位置。一次排序就完成了。以后采用递归的方式分别对前半部分和后半部分排序,当前半部分和后半部分均有序时该数组就自然有序了。
排序过程:
1. package com.five.sort;
2.
3.
4. import java.util.LinkedList;
5. import java.util.Random;
6.
7. public class BinarySort {
8. private static LinkedList<Item> stack = new LinkedList<Item>();
9. public static final int MAX_VALUE = 30000000;
10.
11. public static class Item {
12. int low;
13. int high;
14.
15. public Item() {
16. }
17.
18. public Item(int low, int high) {
19. this.low = low;
20. this.high = high;
21. }
22. }
23.
24. public static void main(String[] args) {
25. Random random = new Random();
26. int[] array = new int[MAX_VALUE];
27. int[] array1 = new int[MAX_VALUE];
28. for(int i=0; i< MAX_VALUE; i++) {
29. int value = random.nextInt() % MAX_VALUE;
30. array[i] =value;
31. array1[i] = value;
32. }
33. sort(array);
34. print(array);
35.
36. System.out.println();
37. long start = System.currentTimeMillis();
38. sort(array, 0, MAX_VALUE-1);
39. System.out.println("time2=" + (System.currentTimeMillis() - start));
40. print(array);
41. }
42.
43. public static void print(int[] array){
44. /*for (int i = 0; i < array.length; i++) {
45. System.out.println(array[i] + " ");
46. }*/
47. System.out.println("=========================");
48. }
49.
50. /**
51. * 快速排序的非递归的实现
52. * @param arr 待排序的数组
53. */
54. public static void sort(int[] arr) {
55. long start = System.currentTimeMillis();
56. int mLow = 0;
57. int mHigh = arr.length - 1;
58. stack.add(new Item(mLow, mHigh));
59. int l;
60. int h;
61. int povit;
62. Item item;
63.
64. while (!stack.isEmpty()) {
65. item = stack.remove(0);
66. l = item.low;
67. h = item.high;
68. povit = arr[item.low];
69.
70. while (l < h) {
71. // 从后往前搜索,找到第一个比key小的值arr[h]下标
72. while (h > l && arr[h] >= povit) {
73. h--;
74. }
75. // 然后进行交互
76. if (l < h) {
77. int temp = arr[h];
78. arr[h] = arr[l];
79. arr[l] = temp;
80. l++;
81. }
82. // 从前往后搜索,找到第一个比key大的值arr[l]的下标
83. while (l < h && arr[l] <= povit) {
84. l++;
85. }
86. // 然后进行交换
87. if (l < h) {
88. int temp = arr[h];
89. arr[h] = arr[l];
90. arr[l] = temp;
91. h--;
92. }
93. }
94. // 进行前半部分
95. if (l > item.low) {
96. stack.add(new Item(item.low, h - 1));
97. }
98. // 进行后半部分
99. if (h < item.high) {
100. stack.add(new Item(l + 1, item.high));
101. }
102. }
103. long end = System.currentTimeMillis();
104. System.out.println("time1=" + (end - start));
105. }
106.
107. /**
108. * 快速排序的递归实现
109. * @param arr 待排序的数组
110. * @param low 最低的下标
111. * @param high 最高的下标
112. */
113. public static void sort(int[] arr, int low, int high) {
114. int l = low;
115. int h = high;
116. int povit = arr[low];
117. while (l < h) {
118. // 从后往前搜索,找到第一个比key小的值arr[h]下标
119. while (h > l && arr[h] >= povit) {
120. h--;
121. }
122. // 然后进行交互
123. if (l < h) {
124. int temp = arr[h];
125. arr[h] = arr[l];
126. arr[l] = temp;
127. l++;
128. }
129. // 从前往后搜索,找到第一个比key大的值arr[l]的下标
130. while (l < h && arr[l] <= povit) {
131. l++;
132. }
133. // 然后进行交换
134. if (l < h) {
135. int temp = arr[h];
136. arr[h] = arr[l];
137. arr[l] = temp;
138. h--;
139. }
140. }
141. // 进行前半部分
142. if (l > low) {
143. sort(arr, low, h - 1);
144. }
145. // 进行后半部分
146. if (h < high) {
147. sort(arr, l + 1, high);
148. }
149. }
150. }
151.
复制代码
程序运行结果如下图:大家可以看到,随机生产了3千万个数据进行排序,非递归的实现方式借助了链表,成功完成了排序,并打印出来了排序时间。
递归的方式,并没有成功实现排序,反而抛出了堆栈溢出的异常。 各位小伙伴们,可以思考一下为什么会出现这样的情况。
递归的方式究竟适合哪些场景? 两种算法的优劣性是怎么样的?欢迎大家讨论!