目录

希尔排序(Java实现)

# 算法步骤

选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;

按增量序列个数 k,对序列进行 k 趟排序;

每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

img

# Code:

/**
 @Project :算法
 @Author : xinyu
 @Date :2022/3/2 下午7:29
 @Description :希尔排序
 **/
package com.atguigu.sort;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

public class ShellSort {

   public static void main(String[] args) {
      //int[] arr = { 8, 9, 1, 7, 2, 3, 5, 4, 6, 0 };
      
      // 创建要给80000个的随机的数组
      int[] arr = new int[8000000];
      for (int i = 0; i < 8000000; i++) {
         arr[i] = (int) (Math.random() * 8000000); // 生成一个[0, 8000000) 数
      }

      System.out.println("排序前");
      Date data1 = new Date();
      SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      String date1Str = simpleDateFormat.format(data1);
      System.out.println("排序前的时间是=" + date1Str);
      
      //shellSort(arr); //交换式
      shellSort2(arr);//移位方式
      
      Date data2 = new Date();
      String date2Str = simpleDateFormat.format(data2);
      System.out.println("排序前的时间是=" + date2Str);
      
      //System.out.println(Arrays.toString(arr));
   }

   // 使用逐步推导的方式来编写希尔排序
   // 希尔排序时, 对有序序列在插入时采用交换法, 
   // 思路(算法) ===> 代码
   public static void shellSort(int[] arr) {
      
      int temp = 0;
      int count = 0;
      // 根据前面的逐步分析,使用循环处理
      for (int gap = arr.length / 2; gap > 0; gap /= 2) {
         for (int i = gap; i < arr.length; i++) {
            // 遍历各组中所有的元素(共gap组,每组有个元素), 步长gap
            for (int j = i - gap; j >= 0; j -= gap) {
               // 如果当前元素大于加上步长后的那个元素,说明交换
               if (arr[j] > arr[j + gap]) {
                  temp = arr[j];
                  arr[j] = arr[j + gap];
                  arr[j + gap] = temp;
               }
            }
         }
         //System.out.println("希尔排序第" + (++count) + "轮 =" + Arrays.toString(arr));
      }
      
      /*
      
      // 希尔排序的第1轮排序
      // 因为第1轮排序,是将10个数据分成了 5组
      for (int i = 5; i < arr.length; i++) {
         // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
         for (int j = i - 5; j >= 0; j -= 5) {
            // 如果当前元素大于加上步长后的那个元素,说明交换
            if (arr[j] > arr[j + 5]) {
               temp = arr[j];
               arr[j] = arr[j + 5];
               arr[j + 5] = temp;
            }
         }
      }
      
      System.out.println("希尔排序1轮后=" + Arrays.toString(arr));//
      
      
      // 希尔排序的第2轮排序
      // 因为第2轮排序,是将10个数据分成了 5/2 = 2组
      for (int i = 2; i < arr.length; i++) {
         // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
         for (int j = i - 2; j >= 0; j -= 2) {
            // 如果当前元素大于加上步长后的那个元素,说明交换
            if (arr[j] > arr[j + 2]) {
               temp = arr[j];
               arr[j] = arr[j + 2];
               arr[j + 2] = temp;
            }
         }
      }

      System.out.println("希尔排序2轮后=" + Arrays.toString(arr));//

      // 希尔排序的第3轮排序
      // 因为第3轮排序,是将10个数据分成了 2/2 = 1组
      for (int i = 1; i < arr.length; i++) {
         // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
         for (int j = i - 1; j >= 0; j -= 1) {
            // 如果当前元素大于加上步长后的那个元素,说明交换
            if (arr[j] > arr[j + 1]) {
               temp = arr[j];
               arr[j] = arr[j + 1];
               arr[j + 1] = temp;
            }
         }
      }

      System.out.println("希尔排序3轮后=" + Arrays.toString(arr));//
      */
   }
   
   //对交换式的希尔排序进行优化->移位法
   public static void shellSort2(int[] arr) {
      
      // 增量gap, 并逐步的缩小增量
      for (int gap = arr.length / 2; gap > 0; gap /= 2) {
         // 从第gap个元素,逐个对其所在的组进行直接插入排序
         for (int i = gap; i < arr.length; i++) {
            int j = i;
            int temp = arr[j];
            if (arr[j] < arr[j - gap]) {
               while (j - gap >= 0 && temp < arr[j - gap]) {
                  //移动
                  arr[j] = arr[j-gap];
                  j -= gap;
               }
               //当退出while后,就给temp找到插入的位置
               arr[j] = temp;
            }

         }
      }
   }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
上次更新: 2023/09/05 17:45:42
最近更新
01
关于我
07-14
02
科学上网
11-15
03
OSS+CDN
09-23
更多文章>
极昼青春
买辣椒也用券