排序算法(1)-冒泡排序,选择排序,插入排序,希尔排序,快速排序

柔光的暖阳◎ 2022-05-23 09:07 310阅读 0赞

一些基本的排序算法:

  1. package tenSortingMethods;
  2. /** * @author zhangdi * @description 排序算法 * @Date 20180531 */
  3. public class Sort {
  4. public static void main(String[] args) {
  5. int[] arr = {
  6. 6,1,2,7,9,3,4,5,10,8};//{ 26, 88, 45, 57, 12, 31, 12, 2, 64, 32, 20, 99, 1 };
  7. int[] arr1 = { 2, 1, 3, 5, 4 };// {6,1,2,7,9,3,4,5,10,8};
  8. // System.out.println(arr.getClass());
  9. System.out.println(" arr before sorting: " + IntArrtoString(arr));
  10. // BubbleSort(arr);
  11. // BubbleSort2(arr);
  12. // BubbleSort1_better(arr);
  13. // SelectSort(arr);
  14. // InsertionSort(arr);
  15. // ShellSort(arr);
  16. // ShellSort2(arr);
  17. // int[] quickSort = new Sort().QuickSort(arr, 0, arr.length - 1);
  18. // System.out.println(" quickSort after sorting: " +
  19. // IntArrtoString(quickSort));
  20. int[] quickSort2 = new Sort().QuickSort2(arr, 0, 9);
  21. // System.out.println(" quickSort2 after sorting: " +
  22. // IntArrtoString(quickSort2));
  23. System.out.println(" arr after sorting: " + IntArrtoString(arr));
  24. }
  25. /** * @description 冒泡排序 * @param arr * @description : 两两比较,大的往后放; 每一次比较完成之后,下一次就少比较一个元素 * 第一次比较有0个元素不比较;第二次有一个元素不需要比较;第三次有两个元素不需要比较; * 共需要比较arr.length-1次 */
  26. public static void BubbleSort(int[] arr) {
  27. int temp;// 临时变量
  28. if (arr == null || arr.length == 0)
  29. return;
  30. for (int i = 0; i < arr.length - 1; i++) { // 表示趟数,一共arr.length-1次。
  31. for (int j = arr.length - 1; j > i; j--) {
  32. if (arr[j] < arr[j - 1]) {
  33. temp = arr[j];
  34. arr[j] = arr[j - 1];
  35. arr[j - 1] = temp;
  36. }
  37. }
  38. }
  39. }
  40. /** * @description 冒泡排序-2 * @param arr * */
  41. public static void BubbleSort2(int[] arr) {
  42. int temp;// 临时变量
  43. if (arr == null || arr.length == 0)
  44. return;
  45. for (int i = 0; i < arr.length - 1; i++) { // 表示趟数,一共arr.length-1次。
  46. for (int j = 0; j < arr.length - 1 - i; j++) {
  47. if (arr[j] > arr[j + 1]) {
  48. temp = arr[j];
  49. arr[j] = arr[j + 1];
  50. arr[j + 1] = temp;
  51. }
  52. }
  53. }
  54. }
  55. /** * @description 冒泡排序-1-优化 * @param arr * * 针对问题:数据的顺序排好之后,冒泡算法仍然会继续进行下一轮的比较,直到arr.length-1次,后面的比较没有意义的。 * 方案: 设置标志位flag,如果发生了交换flag设置为true;如果没有交换就设置为false。 * 这样当一轮比较结束后如果flag仍为false,即:这一轮没有发生交换,说明数据的顺序已经排好,没有必要继续进行下去。 * */
  56. public static void BubbleSort1_better(int[] arr) {
  57. int temp;// 临时变量
  58. boolean flag;
  59. if (arr == null || arr.length == 0)
  60. return;
  61. for (int i = 0; i < arr.length - 1; i++) { // 表示趟数,一共arr.length-1次。
  62. flag = false;
  63. for (int j = arr.length - 1; j > i; j--) {
  64. if (arr[j] < arr[j - 1]) {
  65. temp = arr[j];
  66. arr[j] = arr[j - 1];
  67. arr[j - 1] = temp;
  68. }
  69. }
  70. if (!flag)
  71. break;
  72. }
  73. }
  74. /** * @description 选择排序 * @param arr * 在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换; * 第二次遍历n-2个数,找到最小的数值与第二个元素交换; 。。。 * 第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成。 */
  75. public static void SelectSort(int[] arr) {
  76. int len = arr.length;
  77. int temp;// 临时变量
  78. if (arr == null || len == 0)
  79. return;
  80. for (int i = 0; i < len - 1; i++) {
  81. int minIndex = i;// 假定此时i位置元素为最小数值
  82. for (int j = i + 1; j < arr.length; j++) {
  83. if (arr[j] < arr[minIndex]) {
  84. // 如果i+1后的元素值小于i位置的元素,那么改变minIndex值.当内层循环走完,此时数组最小值得小标就确定了
  85. minIndex = j;
  86. }
  87. }
  88. if (minIndex != i) {
  89. // 最小值下标改变,交换元素
  90. temp = arr[i];
  91. arr[i] = arr[minIndex];
  92. arr[minIndex] = temp;
  93. }
  94. }
  95. }
  96. /** * @description 插入排序 * @param arr * @description : 在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。 * 如此反复循环,直到全部排好顺序。 位于表中后面的元素依次与表中前面的元素比较,若比之小,则还需继续和更前面的元素比较, * 直至遇到一个比它大的元素或者比较到第一个元素(哨兵)了。 */
  97. public static void InsertionSort(int[] arr) {
  98. int len = arr.length;
  99. int temp;// 临时变量
  100. if (arr == null || len == 0)
  101. return;
  102. for (int i = 0; i < len - 1; i++) {
  103. // 趟数n-1趟
  104. for (int j = i + 1; j > 0; j--) {
  105. if (arr[j] < arr[j - 1]) {
  106. temp = arr[j];
  107. arr[j] = arr[j - 1];
  108. arr[j - 1] = temp;
  109. } else {
  110. break;
  111. }
  112. }
  113. }
  114. }
  115. /** * @description 希尔排序 (最小增量排序) * @param arr * @description: 我们选择增量gap=length/2,缩小增量继续以gap = * gap/2的方式,这种增量选择我们可以用一个序列来表示,{n /2,(n/2)/2...1},称为增量序列。 * 希尔排序的增量序列的选择与证明是个数学难题, 我们选择的这个增量序列是比较常用的,也是希尔建议的增量, * 称为希尔增量,但其实这个增量序列不是最优的。 此处我们做示例使用希尔增量。 * 比如原始数组8917235460,初始增量为gap =length/5;即数组被分为五组 * [8,3],[9,5],[1,4],[7,6],[2,0] ,对五组分别进行插入排序;第一次排序后: * 3514089472,缩小增量为gap =gap/2 = * 2;分为两组[3,5,1,4,0],[8,9,4,7,2],插入排序 -->[0214357698], * 再缩小增量gap = gap/ = 1,[0214357698] -->插入排序. * * */
  116. public static void ShellSort(int[] array) {
  117. int temp = 0;
  118. int incre = array.length;
  119. while (true) {
  120. incre = incre / 2;
  121. for (int k = 0; k < incre; k++) { // 根据增量分为若干子序列
  122. for (int i = k + incre; i < array.length; i += incre) {
  123. for (int j = i; j > k; j -= incre) {
  124. if (array[j] < array[j - incre]) {
  125. temp = array[j - incre];
  126. array[j - incre] = array[j];
  127. array[j] = temp;
  128. } else {
  129. break;
  130. }
  131. }
  132. }
  133. }
  134. if (incre == 1) {
  135. break;
  136. }
  137. }
  138. }
  139. /** * @description 希尔排序 (最小增量排序) * @param arr * 在希尔排序的理解时,我们倾向于对于每一个分组,逐组进行处理,但在代码实现中, * 我们可以不用这么按部就班地处理完一组再调转回来处理下一组( 这样还得加个for循环去处理分组)比如[5,4,3,2,1,0] * ,首次增量设gap=length/2=3,则为3组[5,2] [4,1] * [3,0],实现时不用循环按组处理,我们可以从第gap个元素开始,逐个跨组处理。同时,在插入数据时, * 可以采用元素交换法寻找最终位置, 也可以采用数组元素移动法寻觅。 * */
  140. /** * 希尔排序 针对有序序列在插入时采用交换法 见图 * * @param arr */
  141. public static void ShellSort2(int[] arr) {
  142. System.out.println("ShellSort2 start.........");
  143. // 增量gap,并逐步缩小增量
  144. for (int gap = arr.length / 2; gap > 0; gap /= 2) {
  145. // 从第gap个元素,逐个对其所在组进行直接插入排序操作
  146. System.out.println("1 gap:" + gap + " arr:" + IntArrtoString(arr));
  147. for (int i = gap; i < arr.length; i++) {
  148. int j = i;
  149. while (j - gap >= 0 && arr[j] < arr[j - gap]) {
  150. // 插入排序采用交换法
  151. swap(arr, j, j - gap);
  152. j -= gap;
  153. }
  154. System.out.println("2 gap:" + gap + " i:" + i + " arr:" + IntArrtoString(arr));
  155. }
  156. }
  157. System.out.println("ShellSort2 end...........");
  158. }
  159. /** * 希尔排序 针对有序序列在插入时采用移动法。 * * @param arr */
  160. public static void ShellSort3(int[] arr) {
  161. // 增量gap,并逐步缩小增量
  162. for (int gap = arr.length / 2; gap > 0; gap /= 2) {
  163. // 从第gap个元素,逐个对其所在组进行直接插入排序操作
  164. for (int i = gap; i < arr.length; i++) {
  165. int j = i;
  166. int temp = arr[j];
  167. if (arr[j] < arr[j - gap]) {
  168. while (j - gap >= 0 && temp < arr[j - gap]) {
  169. // 移动法
  170. arr[j] = arr[j - gap];
  171. j -= gap;
  172. }
  173. arr[j] = temp;
  174. }
  175. }
  176. }
  177. }
  178. /** * 交换数组元素 * * @param arr * @param a * @param b */
  179. public static void swap(int[] arr, int a, int b) {
  180. arr[a] = arr[a] + arr[b];
  181. arr[b] = arr[a] - arr[b];
  182. arr[a] = arr[a] - arr[b];
  183. }
  184. /** * @param arr * @description 快速排序 基本思想:(分治) 先从数列中取出一个数作为key值; * 将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边; 对左右两个小数列重复第二步,直至各区间只有1个数。 * @ses http://developer.51cto.com/art/201403/430986.htm * https://blog.csdn.net/morewindows/article/details/6684558 */
  185. // 快速排序
  186. public int[] QuickSort(int[] a, int l, int r) {
  187. if (l < r) {
  188. int i = l, j = r, v = a[l];// i:左边开始活动坐标,j:右边开始活动坐标,v:基数,用于对比的值,一般取第一个
  189. while (i < j) {
  190. // 只要左边游标和游标不重叠的话那么就继续遍历
  191. System.out.println("i:" + i + " j:" + j + " arr:" + IntArrtoString(a));
  192. // 每一轮遍历的时候只进行一轮,把右边的一个比基数小的数移动到左边,把左边比基数大的数移动到右边
  193. while (i < j && a[j] > v)
  194. // 找出右边比左边小的坐标
  195. j--;
  196. if (i < j)
  197. a[i++] = a[j];// 进行移动,左边坐标移动一个数
  198. System.out.println("i:" + i + " j:" + j + " arr:" + IntArrtoString(a));
  199. while (i < j && a[i] < v)
  200. // 找出左边比右边大的坐标
  201. i++;
  202. if (i < j)
  203. a[j--] = a[i];// 进行移动,右边坐标移动一个数
  204. System.out.println("i:" + i + " j:" + j + " arr:" + IntArrtoString(a));
  205. }
  206. a[i] = v;// 当游标重叠时填入基数
  207. this.QuickSort(a, l, i - 1);
  208. this.QuickSort(a, i + 1, r);
  209. return a;
  210. }
  211. return a;
  212. }
  213. /** * @param a * @param left * @param right * @return QuickSort2在一轮对比基准数的过程中不移动基准数,减少移动次数 */
  214. public int[] QuickSort2(int[] a, int left, int right) {
  215. //校验要初始化变量之前;不校验易报错:java.lang.ArrayIndexOutOfBoundsException
  216. if (left>right ) {
  217. return a;
  218. }
  219. int i = left, j = right, s = a[left];
  220. int temp;
  221. while (i < j) {
  222. //System.out.println("1--------i:" + i + " j:" + j + " arr:" + IntArrtoString(a));
  223. while (a[j] >= s && j > i) {
  224. j--;
  225. //System.out.println("2--------i:" + i + " j:" + j + " arr:" + IntArrtoString(a));
  226. }
  227. while (a[i] <= s && j > i) {
  228. i++;
  229. //System.out.println("3--------i:" + i + " j:" + j + " arr:" + IntArrtoString(a));
  230. }
  231. if (i < j) {
  232. temp = a[j];
  233. a[j] = a[i];
  234. a[i] = temp;
  235. //System.out.println("4---------i:" + i + " j:" + j + " arr:" + IntArrtoString(a));
  236. }
  237. }
  238. a[left] = a[i];
  239. a[i] = s;
  240. QuickSort2(a, left, i - 1);
  241. QuickSort2(a, i + 1, right);
  242. return a;
  243. }
  244. }

发表评论

表情:
评论列表 (有 0 条评论,310人围观)

还没有评论,来说两句吧...

相关阅读