首先先說shell排序的基本思想:先取一個小於n的整數d1作為第一個增量,把檔案的全部記錄分成d1個組。所有距離為dl的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;然後,取第二個增量d2<d1重複上述的分組和排序,直至所取的增量dt=1(dt<dt-l<;…<d2<d1),即所有記錄放在同一組中進行直接插入排序為止。
Shell排序的執行時間依賴於增量序列。
好的增量序列的共同特徵:① 最後一個增量必須為1;② 應該盡量避免序列中的值(尤其是相鄰的值)互為倍數的情況。
從時間效能上來說希爾排序優於直接插入的原因主要是:
①當檔案初態基本有序時直接插入排序所需的比較和移動次數均較少。②當n值較小時,n和n的差別也較小,即直接插入排序的最好時間複雜度O(n)和最壞時間複雜度0(n^2)差別不大。③在希爾排序開始時增量較大,分組較多,每組的記錄數目少,故各組內直接插入較快,後來增量di逐漸縮小,分組數逐漸減少,而各組的記錄數目逐漸增多,但由於已經按di-1作為距離排過序,使檔案較接近於有序狀態,所以新的一趟排序過程也較快。
下面給出一個對於一組任意產生的數組進行排序的shell實現演算法。:
#include <stdio.h>#include <stdlib.h>#include <time.h>#define MAX 10#define SWAP( x,y) {int t; t = x; x = y; y = t;}void shellsort( int[]);int main( void) { int number[MAX] = {0}; int i; srand( time( NULL)); printf( "排序前:"); for( i = 0; i < MAX; i++) {number[i] = rand( ) % 100;printf( "%d ", number[i]); } shellsort( number); return 0;}void shellsort( int number[]) {int i, j, k, gap, t;gap = MAX / 2;while( gap > 0) { for( k = 0; k < gap; k++) { for( i = k+gap; i < MAX; i+=gap) { for( j = i - gap; j >= k; j-=gap) {if( number[j] > number[j+gap]) { SWAP( number[j], number[j+gap]);} else break; } } } printf( "\ngap = %d:", gap); for( i = 0; i < MAX; i++) printf( "%d ", number[i]); printf( "\n"); gap /= 2;}}
從這段代碼中可以發現由於Shell排序演算法是按增量分組進行的排序,所以Shell排序演算法是一種不穩定的排序演算法。