希爾排序(二)
另一種寫法
上一篇博文希爾排序(一)中的程式碼是基於希爾排序的原理,“直譯”過來的。還有一種更簡單的寫法:
void shellsort_2(int a[], int n)
{
int j, gap;
for (gap = n / 2; gap > 0; gap /= 2)
{
#ifdef PRINT_PROCEDURE
printf("-------- gap = %d--------\n",gap);
print_array(a, n,gap);
#endif
for (j = gap; j < n; j++)//從陣列第 gap個元素開始 ,直到 n-1
{
if ( a[j - gap] > a[j] )//每個元素與自己組內的資料進行直接插入排序
{
int temp = a[j];
int k = j - gap;
while (k >= 0 && a[k] > temp) //&&優先順序更低
{
a[k + gap] = a[k]; // a[k]向後移動 ,騰出一個空位
k -= gap;
}// 考察空位前面的元素
a[k+gap] = temp; //插入
#ifdef PRINT_PROCEDURE
printf("[%d] insert to [%d]\n", j, k+gap);
print_array(a, n,gap);
#endif
}
}
}
}
對希爾排序的改進
希爾排序的執行時間依賴於增量序列的選擇。 舉個例子,如果使用 Shell 建議的序列,假使上一個增量為 4,那麼當前的增量就是 2。因為2是4的因子,所以對於上一輪已經比較過的元素,這一輪會重複比較,這就造成了時間的浪費。更好的增量序列選擇是增量序列中的任何2個元素都是互素的。目前已有學者提出了一些更有效的增量序列,這裡僅展示其中的2個。
Hibbard (希巴德)序列
Hibbard(希巴德)序列:
{1,3,7,...,2^k-1}
(k
為大於 0
的自然數)
使用 Hibbard 增量的希爾排序,其最壞情形的執行時間為
\Theta(n^{3/2})
; 其平均情形的執行時間被認為是
O(n^{5/4})
(基於模擬結果)。
Sedgewick (塞奇威克)序列
已知的最好的增量序列是由 Sedgewick(塞奇威克) 提出的:
1, 5, 19, 41, 109, ....
這個序列中的項交替地取自以下2個序列:
1,19,109,505,2161,...,9*(4^k-2^k)+1
(k=0,1,2,3,...)
5,41,209,929,3905,..., 2^{k+2}(2^{k+2}-3)+1
(k=0,1,2,3,...)
使用 Hibbard 增量的希爾排序平均執行時間猜測為
O(n^{7/6})
,最壞情形為O(n^{4/3})
。
改進後的C語言程式碼
void shell_sort_improved(int A[], int N, int inc_seq[])
{
int inc = 0;
int max_inc_idx = 0;
int i,j,k,tmp;
while (inc_seq[ max_inc_idx + 1 ] < N)
max_inc_idx++; //找到最大的且小於N的那個增量
for (i = max_inc_idx; i >= 0; --i)
{
inc = inc_seq[i];
#ifdef PRINT_PROCEDURE
printf("-------- gap = %d--------\n",inc);
#endif
for (j = inc; j < N; ++j)
{
if( A[j-inc] > A[j] )
{
tmp = A[j];
k = j - inc;
while (k >= 0 && A[k] > tmp)
{
A[ k + inc ] = A[k]; // A[k]向後移動 inc個位置,騰出一個空位
k -= inc; // 繼續考察空位前面的元素
}
A[k + inc] = tmp; // tmp 插入到k的後面
#ifdef PRINT_PROCEDURE
printf("[%d] insert to [%d]\n", j, k+inc);
#endif
}
}
}
}
最後一個引數是增量序列。
完整程式碼及測試
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define PRINT_GAP 10
#define ARRAY_LEN 100
void print_array(int a[], int len, int gap) // 用於列印陣列
{
for(int i=0; i<len; ++i)
{
printf("[%2d]:%2d ", i, a[i]);
if((i + 1) % gap == 0)
printf("\n");
}
printf("\n\n");
}
void shell_sort_improved(int A[], int N, int inc_seq[])
{
int inc = 0;
int max_inc_idx = 0;
int i,j,k,tmp;
while (inc_seq[ max_inc_idx + 1 ] < N)
max_inc_idx++; //找到最大的且小於N的那個增量
for (i = max_inc_idx; i >= 0; --i)
{
inc = inc_seq[i];
#ifdef PRINT_PROCEDURE
printf("-------- gap = %d--------\n",inc);
#endif
for (j = inc; j < N; ++j)
{
if( A[j-inc] > A[j] )
{
tmp = A[j];
k = j - inc;
while (k >= 0 && A[k] > tmp)
{
A[ k + inc ] = A[k]; // A[k]向後移動 inc個位置,騰出一個空位
k -= inc; // 繼續考察空位前面的元素
}
A[k + inc] = tmp; // tmp 插入到k的後面
#ifdef PRINT_PROCEDURE
printf("[%d] insert to [%d]\n", j, k+inc);
#endif
}
}
}
}
int main(void)
{
printf("\n");
int array[ARRAY_LEN];
srand((unsigned int) time(NULL)); //設定隨機數種子
// 產生100個隨機整數,範圍在 [0, 100]
for(int i=0; i<ARRAY_LEN; ++i)
{
array[i] = rand() % 101;
}
print_array(array,sizeof(array)/sizeof(array[0]),PRINT_GAP);
int Sedgewick_seq[] = {1, 5, 19, 41, 109};
shell_sort_improved(array, sizeof(array)/sizeof(array[0]),Sedgewick_seq);
print_array(array,sizeof(array)/sizeof(array[0]),PRINT_GAP);
return 0;
}
執行結果如下圖:
【完】
參考資料
《資料結構與演算法分析(原書第2版)》(機械工業出版社,2004)
相關文章
- 希爾排序——重溫排序(二)排序
- 第二章 :查詢與排序-------希爾排序排序
- 希爾排序排序
- 演算法(二)初等排序前篇[插入和希爾排序]演算法排序
- 希爾排序(一)排序
- Java希爾排序Java排序
- 理解希爾排序排序
- java 希爾排序Java排序
- 排序演算法__希爾排序排序演算法
- 【排序演算法】- 希爾排序排序演算法
- C++希爾排序C++排序
- 希爾排序(C++)排序C++
- 【筆記】希爾排序筆記排序
- 希爾排序(Shell Sort)排序
- 排序演算法之希爾排序排序演算法
- 【排序】插入類排序—(折半)插入排序、希爾排序排序
- 希爾排序java實現排序Java
- PHP 排序演算法之希爾排序PHP排序演算法
- 【資料結構】希爾排序!!!資料結構排序
- 【資料結構】希爾排序資料結構排序
- 排序演算法:Java實現希爾排序排序演算法Java
- 排序演算法總結之希爾排序排序演算法
- 排序演算法 - 快速插入排序和希爾排序排序演算法
- 【小小前端】前端排序演算法第二期(繞人的希爾排序)前端排序演算法
- 排序演算法(氣泡排序,選擇排序,插入排序,希爾排序)排序演算法
- rust-algorithms:14-希爾排序RustGo排序
- JavaScript希爾排序簡單介紹JavaScript排序
- #排序演算法#【2】直接插入排序、希爾排序排序演算法
- 【譯】Swift演算法俱樂部-希爾排序Swift演算法排序
- 【演算法】希爾排序的實現演算法排序
- 七、排序,選擇、冒泡、希爾、歸併、快速排序實現排序
- 三種插入排序 直接插入排序,折半插入排序,希爾排序排序
- python實現希爾排序演算法Python排序演算法
- C#演算法----(三)希爾排序 (轉)C#演算法排序
- 【PHP資料結構】插入類排序:簡單插入、希爾排序PHP資料結構排序
- 希爾排序使用直接插入排序、二分插入排序的C++程式碼實現演算法排序C++演算法
- 程式猿修仙之路--演算法之希爾排序演算法排序
- 基礎演算法系列 之希爾排序演算法排序