希尔(Shell)排序又称为缩小增量排序,它是插入排序算法的一种加强版。它与插入排序的不同之处在于:它会优先和距离较远的元素进行比较。
希尔排序的基本思想:
(1)选择一个希尔增量序列t1,t2,…,tk,(递减序列,tk=1)
(2)按增量序列个数k,对序列进行k 趟排序,
每趟排序,根据对应的增量ti,将待排序列分割成若干子序列,分别对各子序列进行插入排序。
当且仅当增量为1 时,整个序列合成为一组,构成一组有序数字,完成排序。
说明:
(1)希尔增量的起始值不超过整个序列的长度,并且最好选择素数(由经验得出,学者可以尝试一下)。
(2)希尔增量序列是递减的,递减规律自行确定,但一定要保证最后一个希尔增量值为1。
为了方便学者理解掌握,举例说明:
实现9 11 21 25 7 4 12 17 52 28这10个数从小到大的排序
假定希尔增量的初始值为整个序列长度的一半,即t=5,希尔增量的递减规律为t=t/2;希尔排序的过程如下:
第一趟:布尔增量t=5(从左往右,每一个数a和相距为5的数b进行比较,如果a>b,则交换a和b的位置,否则,不交换)
第一趟排序后的序列为:4 11 17 25 7 9 12 21 52 28
第二趟:布尔增量t=5/2=2(从左往右,每一个数a和相距为2的数b进行比较,如果a>b,则交换a和b的位置,否则,不交换)
第二趟排序后的序列为:4 9 7 11 12 21 17 25 52 28
第三趟:布尔增量t=2/2=1(从左往右,每一个数a和相距为1的数b进行比较,如果a>b,则交换a和b的位置,否则,不交换)
第三趟排序后的序列为:4 7 9 11 12 17 21 25 28 52
此时的t等于1,代表完成了整个序列的排序,即最终的序列为:4 7 9 11 12 17 21 25 28 52
希尔排序过程总结:
(1)确定希尔增量t的起始值和递减规律;
(2)从左往右,将步长为t的数分为一个组,组内采用插入排序;
(3)当t等于1时,整个序列合成为一组,采用插入排序,构成一组有序数字,则完成排序。
希尔排序算法分析:
(1)希尔排序是按照不同步长对元素进行插入排序,相等数据可能会交换位置,所以希尔排序是不稳定的算法。
(2)希尔排序中对于增量序列的选择十分重要,直接影响到希尔排序的性能。它的时间复杂度分析很复杂,大致为O(n的3/2次方)到O(n的2次方)之间。
整个过程需要学者理解掌握,如果有什么问题可以提问,更多知识,可以关注我,也可以扫码加入我的知识星球——袁君和他的朋友们,更多的人在这里学习!有算法学习、理财、生活、职场等多方面的知识!
附上完整的代码,和插入排序算法差不多,只是增加了一个希尔增量!
#include
#include
using namespace std;
void ShellSort(int a[],int n) {
int t=n/2;//确定希尔增量的初始值(假设为序列长度的一半)
int i,j,temp;
while(t>=1) { //当增量大于等于1时,执行希尔排序;
// 把距离为 t的元素编为一个组,扫描所有组
for (i = t; i <n; i++) {//每组进行从后往前插入排序
temp = a[i]; //每一组排序的起始位置
for (j = i-t; j >= 0 && temp < a[j]; j = j - t) {
a[j+t] = a[j];//将比temp大的数后移t个位置
}
a[j + t] = temp; //完成插入
}
t= t/ 2; // 减小增量,这里采用折半的方式
}
}
int main ( ) {
int i, k, x;
int a[10]= {9,11,21,25,7,4,12,17,52,28};
printf(“排序前的序列为:\n”);
for (i=0; i<10; i++)
printf("%d “, a[i]);
printf(”\n");
ShellSort(a,10);//调用希尔排序函数,序列长度为10
printf(“排序后的序列(从小到大)为:\n”);
for (i=0; i<10; i++)
printf("%d “, a[i]);
printf(”\n");
return 0;
}