shell排序就是插入排序的一個變化形式,由於插入排序是每一個元素都會進行比較,並拿當前元素和之前的所有元素進行比較,在最壞情況下。因此,DL.Shell於1959年提出了shell排序,也就是分組插入排序,將一個待排序數組進行分組,在多個組之間的對應元素進行插入排序,通過不斷的增加組值,來使待排序數組完成一次排序。因此shell排序也叫做增量插入排序。本人心裏面思考了這個排序,整整想了2天。因此記錄下這個過程了。
假如現在有待排序數組:10,14 ,73 ,25 ,23 ,13 ,27 ,94, 33, 39 ,25 ,59, 94, 65, 82, 45。n=16;
1 那麼我們可以定一個分組gap,gap = n/2。那麼這個數組就分成兩組了。
10,14 ,73 ,25 ,23 ,13 ,27 ,94,
33, 39 ,25 ,59, 94, 65, 82, 45
這樣的話,10和33做比較,14和39做比較,73和25做比較。25和59做比較。。。。後面的依次比較。當gap = 8時,排序的結果是:
10 14 25 25 23 13 27 45
33 39 73 59 94 65 82 94
2 現在在增加gap,gap = n/4 = 4。那麼這個數組就分成四組了。
10 14 25 25
23 13 27 45
33 39 73 59
94 65 82 94
這次比較就是10,23,33,94做比較,14,13,39,65做比較。25,27,73,82做比較,25,45,59,94做比較。此時,排序的結果是:
10 13 25 25
23 14 27 45
33 39 73 59
94 65 82 94
3 現在在增加gap,gap = n/8=2。那麼這個數組就分成8組,進行排序,最後一直到gap=1,也就是普通的插入排序了。
有了以上的過程,我們代碼就比較容易寫出來了。
1 首先是定義gap值,然後每次減少gap的值,來增加分組數量。for(int gap=n/2;gap>0;gap/=2)
2 然後針對每個分組對應的值,進行比較,插入排序。我們預設從第一個gap開始選中元素,一直到數組最後一個元素,我們通過當前選中元素的索引加減gap值,來實現對每一組元素進行比較。
for(int i=gap;i<n;i++){
for(int j=i-gap;j>=0&&a[j]>a[i+gap];j-=gap)
swap(a,j,j+gap);
}
我們來看看完整的代碼吧。
package com.bplead.sort;public class ShellSort {public static void main(String[] args) {int a[] = {10,14 ,73 ,25 ,23 ,13 ,27 ,94, 33, 39 ,25 ,59, 94, 65, 82, 45};int size = a.length;int temp = 0;for(int gap = size/2;gap>0;gap/=2){for(int i=gap;i<size;i++){for(int j=i-gap;j>=0&&a[j]>a[j+gap];j-=gap){temp = a[j];a[j] = a[j+gap];a[j+gap] = temp;}}print(a);}print(a);}private static void print(int a[]){for(int i=0;i<a.length;i++)System.out.print(a[i] +" ");System.out.println();}}
運算結果就和我們之前分析的一樣,如下:
10 14 25 25 23 13 27 45 33 39 73 59 94 65 82 94
10 13 25 25 23 14 27 45 33 39 73 59 94 65 82 94
10 13 23 14 25 25 27 39 33 45 73 59 82 65 94 94
10 13 14 23 25 25 27 33 39 45 59 65 73 82 94 94
10 13 14 23 25 25 27 33 39 45 59 65 73 82 94 94