1. package com.atguigu.sort;
  2. import java.text.SimpleDateFormat;
  3. /**
  4. * @author victor
  5. * @site https://victorfengming.gitee.io/
  6. * @project data_algorithm
  7. * @package com.atguigu.sort
  8. * @created 2021-02-22 20:34
  9. */
  10. import java.text.SimpleDateFormat;
  11. import java.util.Arrays;
  12. import java.util.Date;
  13. public class ShellSort {
  14. public static void main(String[] args) {
  15. //int[] arr = { 8, 9, 1, 7, 2, 3, 5, 4, 6, 0 };
  16. // 创建要给80000个的随机的数组
  17. int[] arr = new int[8000000];
  18. for (int i = 0; i < 8000000; i++) {
  19. arr[i] = (int) (Math.random() * 8000000); // 生成一个[0, 8000000) 数
  20. }
  21. System.out.println("排序前");
  22. Date data1 = new Date();
  23. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  24. String date1Str = simpleDateFormat.format(data1);
  25. System.out.println("排序前的时间是=" + date1Str);
  26. //shellSort(arr); //交换式
  27. shellSort2(arr);//移位方式
  28. Date data2 = new Date();
  29. String date2Str = simpleDateFormat.format(data2);
  30. System.out.println("排序前的时间是=" + date2Str);
  31. //System.out.println(Arrays.toString(arr));
  32. }
  33. // 使用逐步推导的方式来编写希尔排序
  34. // 希尔排序时, 对有序序列在插入时采用交换法,
  35. // 思路(算法) ===> 代码
  36. public static void shellSort(int[] arr) {
  37. int temp = 0;
  38. int count = 0;
  39. // 根据前面的逐步分析,使用循环处理
  40. for (int gap = arr.length / 2; gap > 0; gap /= 2) {
  41. for (int i = gap; i < arr.length; i++) {
  42. // 遍历各组中所有的元素(共gap组,每组有个元素), 步长gap
  43. for (int j = i - gap; j >= 0; j -= gap) {
  44. // 如果当前元素大于加上步长后的那个元素,说明交换
  45. if (arr[j] > arr[j + gap]) {
  46. temp = arr[j];
  47. arr[j] = arr[j + gap];
  48. arr[j + gap] = temp;
  49. }
  50. }
  51. }
  52. //System.out.println("希尔排序第" + (++count) + "轮 =" + Arrays.toString(arr));
  53. }
  54. /*
  55. // 希尔排序的第1轮排序
  56. // 因为第1轮排序,是将10个数据分成了 5组
  57. for (int i = 5; i < arr.length; i++) {
  58. // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
  59. for (int j = i - 5; j >= 0; j -= 5) {
  60. // 如果当前元素大于加上步长后的那个元素,说明交换
  61. if (arr[j] > arr[j + 5]) {
  62. temp = arr[j];
  63. arr[j] = arr[j + 5];
  64. arr[j + 5] = temp;
  65. }
  66. }
  67. }
  68. System.out.println("希尔排序1轮后=" + Arrays.toString(arr));//
  69. // 希尔排序的第2轮排序
  70. // 因为第2轮排序,是将10个数据分成了 5/2 = 2组
  71. for (int i = 2; i < arr.length; i++) {
  72. // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
  73. for (int j = i - 2; j >= 0; j -= 2) {
  74. // 如果当前元素大于加上步长后的那个元素,说明交换
  75. if (arr[j] > arr[j + 2]) {
  76. temp = arr[j];
  77. arr[j] = arr[j + 2];
  78. arr[j + 2] = temp;
  79. }
  80. }
  81. }
  82. System.out.println("希尔排序2轮后=" + Arrays.toString(arr));//
  83. // 希尔排序的第3轮排序
  84. // 因为第3轮排序,是将10个数据分成了 2/2 = 1组
  85. for (int i = 1; i < arr.length; i++) {
  86. // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
  87. for (int j = i - 1; j >= 0; j -= 1) {
  88. // 如果当前元素大于加上步长后的那个元素,说明交换
  89. if (arr[j] > arr[j + 1]) {
  90. temp = arr[j];
  91. arr[j] = arr[j + 1];
  92. arr[j + 1] = temp;
  93. }
  94. }
  95. }
  96. System.out.println("希尔排序3轮后=" + Arrays.toString(arr));//
  97. */
  98. }
  99. }

希尔排序的算法就比较巧妙了

他能够先将小的放一边,大的分一边

通过2的指数的次数 将总数进行分割

这样的步长,能够快速的实现分类

最后在通过简单的插入排序就ok

希尔排序法应用实例:

imgimgimg
有一群小牛, 考试成绩分别是 {8,9,1,7,2,3,5,4,6,0} 请从小到大排序. 请分别使用
希尔排序时, 对有序序列在插入时采用交换法, 并测试排序速度.
希尔排序时, 对有序序列在插入时采用移动法, 并测试排序速度

  1. 排序前
  2. 排序前的时间是=2021-02-22 21:05:44.904
  3. 排序前的时间是=2021-02-22 21:05:46.745
  4. Process finished with exit code 0

注意这个速度是算的 8000000的数据排序的

这个可比之前的快多了