您的位置:首页 > 运维架构 > Shell

《C算法》读书笔记8:shell sort

2015-08-25 23:46 696 查看
希尔排序 shellsortshell \quad sort是变种的插入排序 insertsortinsert \quad sort。在面对部分有序数据的时候,插入排序的效率接近O(n)O(n),因为插入排序的交换效率直接取决于逆序数对的数量。

插入排序的缺点是两次相邻的外循环不能交换太远的项ItemItem,必须依次从左到右进行,假如运气不好,最小键所在项在最右边,就得需要N步才能结束。

void insert_sort2(int *a, int l, int r)
{
int step = 0;
iter1:
for(int i = l + 1; i <= r; ++ i)
{
int j = i;
int v = a[i];
while(j >= l + 1 && LT(v, a[j - 1]))
{
a[j] = a[j - 1];
-- j;
++ step;
}
a[j] = v;
}
printf("insert sort step: %d\n", step);
}


希尔排序的改进是在外循环iter1外面再增加偏移量h,每次重排后得到如下性质:每隔h取一项,使得该新数组为有序。依次减少偏移量,到最后一次使偏移量为1。因前言所述插入排序的性质,每次排序都可以用插入排序完成。

值得重视的是偏移量的选取方式。在对一组随机生成的N=10000的数据统计后,发现以下几种偏移量较为佳。

(1):4095 2047 1023 511 255 127 63 31 15 7 3 1 hn=hn+1∗2+1h_n=h_{n+1}*2+1

(2):3280 1093 364 121 40 13 4 1 hn=hn+1∗3+1h_n=h_{n+1}*3+1

而下面的方式效果不佳:

(1):4096 2048 1024 512 256 128 64 32 16 8 4 2 1 hn=hn+1∗2h_n=h_{n+1}*2

void shell_sort(int *a, int l, int r)
{
int h;
for(h = 1; h <= (r - l) / 4; h = 2 * h);
int step = 0;
for(; h; h /= 2)
{
printf("%d ", h);
for(int i = l + h; i <= r; ++ i)
{
int j = i;
int v = a[i];
while(j >= l + h && LT(v, a[j - h]))
{
a[j] = a[j - h];
j -= h;
++ step;
}
a[j] = v;
}
}
printf("\nshell sort step %d\n", step);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: