希爾排序
基本介紹
希爾排序是希爾(DonaldShell)於1959年提出的一種排序算法。希爾排序也是一種插入排序,它是簡單插入排序經過改進之後的一個更高效的版本,也稱爲縮小增量排序。
插入排序文章:插入排序
希爾排序法基本思想:
希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序算法排序;隨着增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,算法便停止。
希爾排序算法的過程
原始數組:8 9 1 7 2 3 5 4 6 0
初始增量 gap = length / 2 = 5,意味着整個數組被分爲5組,[8,3] [9,5,] [1,4] [7,6] [2,0]
對這5組分班進行直接插入排序,結果如下,可以看到,像3,5,6這些小元素,都被調到了前面,然後縮小增量gap = 5 / 2 = 2,數組被分爲 2 組 [3,1,0,9,7] [5,6,8,4,2]
進行一輪之後:3 5 1 6 0 8 9 4 7 2
對以上2組再分班進行直接插入排序,結果如下,可以看到,此時整個數組的有序成都更進一步,再縮小增量gap = 2 / 2 = 1,此時,整個數組爲1組[0,2,1,4,3,5,7,6,9,8]
又進行一輪之後:0 2 1 4 3 5 7 6 9 8
經過上面的“宏觀調控”,整個數組的有序化程度成果喜人。此時,僅僅需要對以上數列簡單微調,無序大量移動操作即可完成整個數組的排序。
最終結果: 0 1 2 3 4 5 6 7 8 9
代碼實現交換法(不推薦使用)
package sort;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ShellSort {
public static void main(String[] args) {
//int[] arr1 = {8,9,1,7,2,3,5,4,6,0};
//測試希爾排序速度,給80000個數據,測試
//創建一個80000個隨機的數組
int[] arr = new int[80000];
for (int i = 0;i < 80000;i ++) {
//會生成一個[0,8000000]的數
arr[i] = (int)(Math.random() * 8000000);
}
//System.out.println("最開始的數組爲:" + Arrays.toString(arr));
Date date1 = new Date();
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1Str = simpleDateFormat1.format(date1);
System.out.println("排序前的時間:" + date1Str);
//測試希爾排序
shellSort(arr);
Date date2 = new Date();
String date2Str = simpleDateFormat1.format(date2);
System.out.println("排序後的時間:" + date2Str);
}
public static void shellSort(int[] arr) {
int temp = 0;
//設置每次的步長,如第一次分爲五組,則步長爲5
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;
}
}
}
}
}
}
不推薦原因:未使用到插入排序的思想,而是使用的冒泡排序思想,導致運行速度負提示。
代碼實現移動法(推薦使用)
package sort;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ShellSort {
public static void main(String[] args) {
//int[] arr1 = {8,9,1,7,2,3,5,4,6,0};
//測試希爾排序速度,給80000個數據,測試
//創建一個80000個隨機的數組
int[] arr = new int[80000];
for (int i = 0;i < 80000;i ++) {
//會生成一個[0,8000000]的數
arr[i] = (int)(Math.random() * 8000000);
}
//System.out.println("最開始的數組爲:" + Arrays.toString(arr));
Date date1 = new Date();
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1Str = simpleDateFormat1.format(date1);
System.out.println("排序前的時間:" + date1Str);
//測試希爾排序
shellSort(arr);
Date date2 = new Date();
String date2Str = simpleDateFormat1.format(date2);
System.out.println("排序後的時間:" + date2Str);
}
public static void shellSort(int[] arr) {
//設置每次的步長,如第一次分爲五組,則步長爲5
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;
}
//當退出循環之後,就給temp找到了插入的位置
arr[j] = temp;
}
}
}
}
}
筆記源自:韓順平數據結構與算法