排序专栏:希尔排序
Posted 电脑小白路漫漫
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序专栏:希尔排序相关的知识,希望对你有一定的参考价值。
讲今天的希尔排序之前,我们不妨复习一下插入排序
插入排序的代码如下:
int main(void)
{
int a[10] = {4, 3, 6, 9, 8, 1, 2, 5, 0, 7};
int i, j ,temp;
for (i=1; i<10; i++) {
temp = a[i];
for (j = i; j > 0 && a[j-1] > temp; j--)
a[j] = a[j-1];
a[j] = temp;
}
for (i=0; i<10; i++) {
printf("%d ", a[i]);
}
return 0;
}
如果你不了解插入排序,请点这个链接:
插入排序法到底快还是慢呢?
现在有一组数:1 2 3 5 4
冒泡排序法需要比较需要:4+3+2+1 = 10次
插入排序法只需要:1+1+1+2 = 5次
看起来在处理小规模数据的时候,插入排序还是很快的?
但是,如果数据是这样的:5 4 3 2 1
插入排序就需要:1+2+3+4 = 10次
同样一组数,插入排序法处理数据的时间相差很大
这是因为插入排序消耗的时间跟这组数的有序性有关。
那么如何让插入排序变得更快呢?
那就是增加原数据的有序性
何以增加?
希尔排序!
希尔排序本质上也是插入排序,所以不会像快速排序和归并排序那样让人难以理解。
为了让大家能掌握希尔排序,我们同样先举一个例子:
8 3 2 7 4 1 5 6
在插入排序中,我们首先让3跟8比较再让2跟8 比较。
也就是说,插入排序时,我们比较的时与我们选中的相邻的元素。
我们的希尔排序则不同,每次选中的是跟这个这个元素相隔很远的元素。
具体是多远呢?
上面这组数据有8个数,我们最远能相隔4个,这样就可以确保每个元素都有相对应的值跟他比较。
8——4 ==> 4——8
3——1 ==> 1——3
2——5 ==> 2——5
7——6 ==> 6——7
首次比较完毕。现在数据变成了:
4 1 2 6 8 3 5 7
你可能会有些疑惑,为什么会跟插入排序很像呢?别急
刚才我们的间隔是4,也就是整个数列的一半
现在我们将间隔变成原来的一半,也就是2。
整个数列我们可以这样看
4 2 8 5
1 6 3 7
这时候我们分成了两组,我们对这两组进行插入排序
得到的是:
2 4 5 8
1 3 6 7
合并之后就是:
2 1 4 3 5 6 8 7
此时如法炮制,继续将间隔减半,此时间隔成了1
此时做插入排序:
就可以得到原来的有序的队列:
1 2 3 4 5 6 7 8
总的来说,希尔排序就是改变插入排序时对比的间隔,来时排序消耗的时间变得更短。虽然在规模小的数据中看不出但,但在处理大规模数据的时候,希尔排序是比插入排序快很多的。
现在我们来看看希尔排序的代码吧:
int main(void)
{
int a[10] = {4, 8, 6, 9, 7, 2, 1, 0, 3, 5};
int i, j, z;
int temp;
for (z = 5; z > 0; z /= 2) {
for (i = z; i < 10; i++){
temp = a[i];
for (j = i; j >= z && a[j - z] > temp; j-=z) {
a[j] = a[j - z];
}
a[j] = temp;
}
}
for (i=0; i<10; i++)
printf("%d ", a[i]);
return 0;
}
跟插入排序比起来,差不多就多了一层for循环,在第9行的z代表了间隔,最开始为整个数列的一半,每轮等于原来的一半。
在第一层for循环内部,关于i的for循环则代表选中的元素。j的for循环代表比较的元素,并且之间相隔z个元素。其余的地方跟插入排序法一摸一样。
希尔排序并不是很难。大家应该很轻松就能理解。
那么本期推送就到这里了,谢谢大家
以上是关于排序专栏:希尔排序的主要内容,如果未能解决你的问题,请参考以下文章