一、引入希爾排序
通過理解直接插入排序的算法,我們可以發現算法的時間耗費主要在查找合適位置和移動元素爲待排元素騰位置。
因此,直接插入排序算法,在待排序的元素序列基本有序且序列元素較少時,其性能最佳!
而希爾排序就是利用了直接插入排序最佳性能的兩個性質,因爲它可以通過算法實現使序列越來越有序(不到最後
一步,都不是真正有序)且元素較少!所以在時間耗費上,希爾排序較直接插入排序性能有較大的改進!
二、希爾排序算法思路:
說算法思路之前,我想應該先介紹一下什麼是增量序列!
所謂增量序列,就是一列數!這一列數的作用就是用來爲待排序序列分組用的,而且這個序列有個特點:最後一
個元素必須是1!
舉例子如下圖:
由上圖可以很簡單總結出希爾排序算法思路:
就是將整個待排序的大序列通過增量序列分解爲多個小序列,然後對每個小序列進行直接插入排序。如此反覆多次(次數與增量序列有關,增量序列有多少個元素,就反覆多少次)。等到按照所有增量序列元素所分的每個小序列都進行直接插入排序後,序列即被排好序!
三、源代碼實現:
/*
**功能: 對一個增量產生的所有序列進行直接插入排序
**參數說明:
**@record : 待排序列數組 @len : 待排序列長度
**@delta : 此次劃分子序列的增量
**返回值 : 無
*/
void ShellInsertSort(int record[], int len, int delta)
{
int i = 0, j;
int value; //保存待插入的元素的值
//0+delta 爲第一個子序列的第二個元素的下標(直接插入排序是從序列的第二個元素開始的)
// i 每次自增以後都會是某一個子序列的第二個元素或之後的元素的下標。
for (i = 0 + delta; i < len; i++)
{
if (record[i] < record[i - delta])
{//該子序列未有序
value = record[i];
//爲value尋找合適的插入位置(移動元素)
for (j = i - delta; j >= 0 && value < record[j]; j -= delta)
{
record[j + delta] = record[j];
}
//將value插入合適的位置
record[j + delta] = value;
}
}
}
/*
**功能: 希爾排序算法升序排序一個序列
**參數說明:
**@record : 序列數組 @len : 序列長度
**@delta : 增量序列數組 @n : 增量序列長度
**返回值: 無
*/
void ShellSort(int record[], int len, int delta[], int n)
{
int i;
for (i = 0; i < n;i++)
{
ShellInsertSort(record, len, delta[i]); //對一個增量產生的所有序列進行直接插入排序
}
}
int main(void)
{
int record[] = { 46,55,13,42,94,17,05,70 }; //待排序列數組
int delta[] = { 4,2,1 }; //增量數組
int len = sizeof(record) / sizeof(record[0]);
int n = sizeof(delta) / sizeof(delta[0]);
int i = 0;
printf("排序前: \n");
for (i = 0;i < len;i++)
{
printf("%d ", record[i]);
}
puts("");
ShellSort(record, len, delta, n);
printf("排序後: \n");
for (i = 0;i < len;i++)
{
printf("%d ", record[i]);
}
puts("");
return 0;
}
運行截圖: