PageRenderTime 36ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/org.hxzon.util/org/hxzon/util/sort/QuickSort.java

https://gitlab.com/mstar-hxzon/mstar-mybatis-hxzon
Java | 167 lines | 77 code | 12 blank | 78 comment | 10 complexity | 84e68fc6582894a582b6eab8bc2fd4e3 MD5 | raw file
  1. package org.hxzon.util.sort;
  2. import java.util.Comparator;
  3. public class QuickSort {
  4. public static <T> void quickSort(T objs[], Comparator<T> comp) {
  5. quickSort(objs, 0, objs.length - 1, comp);
  6. }
  7. public static <T> void quickSort(T objs[], int left, int right, Comparator<T> comp) {
  8. if (left >= right) {
  9. return;
  10. }
  11. int vi = median3Index(objs, left, right, (right + left) / 2, comp);
  12. debug(objs[left] + "," + objs[right] + "," + objs[(right + left) / 2] + ",select:" + objs[vi]);
  13. swap(objs, left, vi);//选择“主元”,放在第一个位置
  14. //
  15. int i = left + 1;
  16. int j = right;
  17. while (true) {
  18. //顺序很重要,要先从右边开始找
  19. while (comp.compare(objs[j], objs[left]) > 0) {
  20. j--;
  21. }
  22. while (comp.compare(objs[i], objs[left]) < 0) {
  23. i++;
  24. }
  25. if (i < j) {
  26. swap(objs, i, j);
  27. debug(objs, left, right);
  28. i++;
  29. j--;
  30. } else {
  31. break;
  32. }
  33. }
  34. debug(objs, left, right);
  35. //
  36. swap(objs, left, i - 1);//vi=i-1
  37. debug("final:");
  38. debug(objs, left, right);
  39. //
  40. quickSort(objs, left, i - 2, comp);//vi-1
  41. quickSort(objs, i, right, comp);//vi+1
  42. }
  43. //===========================
  44. public static <T> void quickSort2(T objs[], Comparator<T> comp) {
  45. quickSort2(objs, 0, objs.length - 1, comp);
  46. }
  47. public static <T> void quickSort2(T objs[], int left, int right, Comparator<T> comp) {
  48. if (left >= right) {
  49. return;
  50. }
  51. int vi = median3Index(objs, left, right, (right + left) / 2, comp);
  52. swap(objs, left, vi);
  53. //
  54. int i = left + 1;
  55. int m = left;
  56. for (; i <= right; i++) {
  57. if (comp.compare(objs[i], objs[left]) < 0) {
  58. swap(objs, ++m, i);
  59. }
  60. }
  61. swap(objs, left, m);
  62. quickSort2(objs, left, m - 1, comp);
  63. quickSort2(objs, m + 1, right, comp);
  64. }
  65. public static <T> int median3Index(T objs[], int a, int b, int c, Comparator<T> comp) {
  66. int bigger = comp.compare(objs[a], objs[b]) > 0 ? a : b;
  67. return comp.compare(objs[bigger], objs[c]) < 0 ? bigger : c;
  68. }
  69. public static <T> void swap(T a[], int i, int j) {
  70. T tmp = a[i];
  71. a[i] = a[j];
  72. a[j] = tmp;
  73. }
  74. public static void debug(Object objs[], int left, int right) {
  75. for (int i = left; i <= right; i++) {
  76. System.out.print(objs[i] + " ");
  77. }
  78. System.out.println();
  79. }
  80. public static void debug(Object o) {
  81. System.out.println(o);
  82. }
  83. //算法思想:以第一个元素为准,小于该元素的放在左边,不小于该元素的放在右边,然后对两侧元素递归排序。
  84. //快速排序的每一轮处理其实就是将这一轮的基准数归位,直到所有的数都归位为止,排序就结束了。
  85. //
  86. //改进:快速排序有一个很大不足就是对于比较有序的数组排序效率很低,而且当数组较短时快速排序并不是最快的。
  87. //应对这些情况有三种简单常用的改进:
  88. //随机化改进:不是选取第一个值为基准,而是随机选取。
  89. //平衡化改进:取第一个、最后一个和中间点三个值中中间值为基准进行排序。
  90. //设置阀值--混合排序:当数组长度小于某一值时使用其他较快的排序。
  91. //
  92. //算法分析:
  93. //时间代价:最好情况是O(n log n),最坏情况是O(n2)。
  94. //如果设f(n)为数组长为n时的比较次数,则f(n)=[(f(1)+f(n-1))+(f(2)+f(n-2))+...+(f(n-1)+f(1))]/n.
  95. //利用数学知识易知f(n)=(n+1)*[1/2+1/3+...+1/(n+1)]-2n~1.386nlog(n).
  96. //空间代价:程序所需的空间即为堆栈深度(用于存储l,u,m),所以空间代价为O(log(n))
  97. //稳定性:快速排序时不稳定的,即不保序的。
  98. //
  99. //评价:快速排序的时间代价比较低,空间代价也比较低,算是时空代价相当好的算法。
  100. //而且在下面的数值试验中也会发现,快速排序效率还是很好的。
  101. //但是最大的不足使快速排序不稳定。
  102. //比如在excel中进行排序,我们自然希望排序结果是稳定的(即相同的数排序后与原来的顺序相同)。
  103. //错误版本1:
  104. // while (true) {
  105. // //顺序很重要,要先从右边开始找
  106. // //(while j>i && ...) is error
  107. // while (j >= left + 1 && comp.compare(objs[j], objs[left]) > 0) {
  108. // j--;
  109. // }
  110. // //(while i<j && ...) is error
  111. // //(while ... && <0) is error
  112. // while (i <= right && comp.compare(objs[i], objs[left]) < 0) {
  113. // i++;
  114. // }
  115. // if (i < j) {
  116. // swap(objs, i, j);
  117. // debug(objs, left, right);
  118. // i++;
  119. // j--;
  120. // }
  121. // if(i>=j) {//这里应改为else,否则,i++,j--后,值为比较就退出了
  122. // break;
  123. // }
  124. // }
  125. //92, 10, 21, 3, 38, 5, 62, 92, 4, 12, 57, 66, 3, 4
  126. //92,4,62,select 62
  127. //[62],10,21,3,38,5,92_,92,4,12,57,66,3,4
  128. //[62],10,21,3,38,5,92_i,92,4,12,57,66,3,4_j
  129. //[62],10,21,3,38,5,4_i,92,4,12,57,66,3,92_j
  130. //[62],10,21,3,38,5,4,92_i,4,12,57,66,3_j,92
  131. //[62],10,21,3,38,5,4,3_i,4,12,57,66,92_j,92
  132. //[62],10,21,3,38,5,4,3,4,12,57_j,66_i,92,92
  133. //57_,10,21,3,38,5,4,3,4,12,[62],66,92,92
  134. //
  135. //57,12,38,select 38
  136. //[38],10,21,3,57_,5,4,3,4,12
  137. //[38],10,21,3,57_i,5,4,3,4,12_j
  138. //[38],10,21,3,12_i,5,4,3,4,57_j
  139. //[38],10,21,3,12,5,4,3,4,57_i (j=0)
  140. //4_,10,21,3,12,5,4,3,[38],57
  141. //
  142. //4,3,3,select 3
  143. //[3],10,21,4_,12,5,4,3
  144. //[3],10_i,21,4,12,5,4,3 (j=0)(if find cond is <=0,then 3 can change with 10)
  145. //[3]_,10,21,4,12,5,4,3
  146. //
  147. //10,3,12,select 10
  148. //[10],21,4,12,5,4,3
  149. //[10],21_i,4,12,5,4,3_j change
  150. //[10],3_i,4,12,5,4,21_j
  151. //[10],3,4,12_i,5,4_j,21 change
  152. //[10],3,4,4_i,5_ni_nj,12_j,21 stop
  153. //[10],3,4,4_,5_i_j,12,21
  154. //4_,3,4,[10],5,12,21 error here,10 now before 5
  155. }