上篇我們對直接插入排序有了一定的瞭解,並且明確知道插入排序最佳排序算法則是O(n),且適合短序列的排序情況,本篇我們講述的shell排序則有效的利用了插入排序的這兩個性質。
shell排序的眼光:不同於直接插入排序的相鄰記錄之間的比較,而是着眼於那些不相鄰的記錄進行比較和移動,待比較到最後,當間距減少爲1時,也就是整個序列接近於一個正序的狀態,然後再對整個序列進行插入排序。
本篇我們採用數組長度n=8,增量每次除以2遞減的方式來選擇增量,即增量序列爲(2^2,2^1,2^0),圖示如下:
根據所寫代碼來走行走一遍的話,簡單流程如下:array[] 以下用A[]表示:
d value | i value | j value | 比較A[] |
---|---|---|---|
d=4 | i=4 | j=4 | A[4]和A[0] |
i=5 | j=5 | A[5]和A[1] | |
i=6 | j=6 | A[6]和A[2] | |
i=7 | j=7 | A[7]和A[3] | |
d=2 | i=2 | j=2 | A[2]和A[0] |
i=3 | j=3 | A[3]和A[1] | |
i=4 | j=4 | A[4]和A[2] | |
i=5 | j=6 | A[5]和A[3] | |
i=6 | j=6 | A[6]和A[4] | |
i=7 | j=7 | A[7]和A[5] | |
d=1 | i=1 | j=1 | A[1]和A[0] |
i=2 | j=2,j=1 | A[2]和A[1],A[1]和A[0] | |
…. | |||
i=7 | j=7,j=6,j=5,j..j=1 | A[7]和A[6],A[6]和A[5]…A[1]和A[0] |
最後實現的簡單代碼:
public static void main(String[] args) {
//定義的數組
int[] array = {16, 11, 14, 13, 4, 33, 22, 11};
ShellSort2 shellSort = new ShellSort2();
shellSort.shellSort(array);
System.out.println(Arrays.toString(array));
}
void shellSort(int[] array) {
int delta;
int n = array.length;
//間隔-增量每次除以2遞減的方式來選擇增量,也就是4,2,1
for (delta = n / 2; delta > 0; delta /= 2) {
int tempRecord = 0;
for (int i = delta; i < array.length; i++) {
tempRecord = array[i];
int j = i;
while (j > delta - 1 && tempRecord < array[j - delta]) {
array[j] = array[j - delta];
j -= delta;
}
array[j] = tempRecord;
}
}
}
至於shell的時間複雜度這裏則不變多說,因爲負責度和增量的設置息息相關。下篇我們則介紹直接插入排序和shell排序運行時間的比較。