希尔排序,shell sort
思想:将待排序列分解为若干序列,再对其进行插入排序,是插入排序的高效改进。
ps:希尔表示他和该算法并没有什么关系。。。。
例:
待排数组:{8,12,3,15,9,11,22,14,13,10}
第一次排序
1) 确定步长
一般的初次取序列的一半为增量,以后每次减半,直到增量为1。
确定步长为10/2=5
2)序列分组
{8,11},{12,22},{3,14},{15,13},{9,10}
3)对分组序列进行插入排序
第一次排序结果
8,12,3,13,9,11,22,14,15,10
第二次排序
1) 确定步长
5/2=2
2) 序列分组
{8,3,9,22,15}
{12,13,11,14,10}
3)对分组序列进行插入排序
{3,8,9,15,22}
{10,11,12,13,14}
第二次排序结果为
3,10,8,11,9,12,15,13,22,14
第三次排序
1) 确定步长
2/2=1 步长为1即可确定最终的排序结果。
2)序列分组
3,10,8,11,9,12,15,13,22,14
3)对分组进行插入排序
最终结果:
3,8,9,10,11,12,13,14,15,22
代码实现
int step,i,j;
for (step = n / 2; step > 0; step /= 2) //步长依次为5,2,1
for (i = 0; i < step; i++){
for (j = i + step; j < n; j += step) {
if (a[j] < a[j - step]){
int temp = a[j]; //保存较小的值到temp中
int k = j - step;
while (k >= 0 && a[k] > temp){
a[k + step] = a[k];//元素替换,将较大的数替换到序列较后的位置
k -= step;
}
a[k + step] = temp; //将temp赋给序列较前的位置
}
}
}
}
希尔排序效率高于普通插入排序
1.当序列基本有序时直接插入排序所需比较次数及移动次数均较少。
2.当序列初始无序时
由于步长较大,所以组内元素较少,分组较多,插入较快。
当步长逐渐缩小,分组逐渐减少,组内元素逐渐增多时,此时序列已基本实现有序,插入次数相对较少。
3.希尔排序是不稳定排序,即组内有相同元素时,未排序之前和排序之后的位置会发生变化。