希尔排序(C语言)

算法原理

算法思想

希尔排序(Shell Sort)是插入排序的一种更高效的改进版本,也称为缩小增量排序。它基于增大元素之间的比较与交换间距的思想,先将待排记录表按间隔D分成若干子序列,然后利用插入排序完成子序列内排序,再渐次减小间隔D重复上述分组插入排序操作,直至D=1为止。希尔排序示意图

算法示例

增量按指数递减

算法分析

也许,初次接触希尔算法时,会感到奇怪,为什么,希尔排序算法使用了多次的插入排序,复杂度反而更小呢?

因为,越接近有序的序列,插入排序算法所需的比较和移动次数越少。
插入排序算法分析

按最坏的情况考虑,不妨假设 n = 2 k n=2^k n=2k,对长度为 n n n的序列,D依次为 2 k − 1 … 1 2^{k-1}\dots 1 2k11,则,比较次数为 ∑ 2 k − 1 + 2 k − 2 ∗ ( 2 ∗ 2 ) + 2 k − 3 ∗ ( 4 ∗ 4 ) … 1 ∗ 2 k − 1 ∗ 2 k − 1 = ∑ i = 0 k − 1 2 k − 1 + i = 2 k − 1 ( 2 k − 1 ) = n 2 − n 2 = O ( n 2 ) \sum2^{k-1}+2^{k-2}*(2*2)+2^{k-3}*(4*4)\dots1*2^{k-1}*2^{k-1}=\sum\limits_{i=0}^{k-1} 2^{k-1+i}=2^{k-1}(2^k-1)=\frac {n^2-n}{2}=O(n^2) 2k1+2k2(22)+2k3(44)12k12k1=i=0k12k1+i=2k1(2k1)=2n2n=O(n2)

最好的情况,比较次数为 ∑ 2 k − 1 + 2 k − 2 ∗ ( 2 ∗ 1 ) + 2 k − 3 ∗ ( 4 ∗ 1 ) … 1 ∗ 2 k − 1 = k 2 k − 1 = n 2 log ⁡ 2 n = O ( n log ⁡ n ) \sum2^{k-1}+2^{k-2}*(2*1)+2^{k-3}*(4*1)\dots1*2^{k-1}=k2^{k-1}=\dfrac{n}{2}\log_2n=O(n\log n) 2k1+2k2(21)+2k3(41)12k1=k2k1=2nlog2n=O(nlogn)

平均性能介乎二者之间,为 n 1.5 n^{1.5} n1.5

希尔排序算法的复杂度

稳定性分析

插入排序是不稳定的,希尔排序可以视为一种特殊的插入排序,自然也是不稳定的。

算法实现

/*按指数递减增量序列进行希尔排序*/
void ShellSort(SqTable &L) {
	n = L.Len;
	for (d = n/2;d > 2;d /= 2) // 增量n/2、n/4、…
		for (j = 1;j <= d;j++) // 对d个子表排序
			InsertSort2(&L.r[j],n+1-j,d)InsertSort2(&L.r[1],n,1)//ShellSort
void InsertSort2(RcdType A[], int n,int incr) {
	for (i = incr; i <= n; i += incr)
	for (j=i; (j>=incr)&&(A[j].key<A[j-incr].key);j-=incr)
		swap(A[j],A[j-incr]);
}//InsertSort2
/*按任意递减增量序列进行希尔排序*/
void ShellSort(SqTable &L, int dlta[], int t) { 
	for (int k=0; k<t; ++k) 
		ShellInsert(L, dlta[k]);
} //ShellSort
/*一趟增量为dk的插入排序*/
void ShellInsert(SqTable &L, int dk) {
	for (i=dk+1; i<=L.len; i++)
	if (L.r[i].key < L.r[i-dk].key) { 
		L.r[0] = L.r[i]; // 暂存在L.r[0]
		for (j=i-dk; j>0&&L.r[0].key<L.r[j].key; j-=dk)
			L.r[j+dk] = L.r[j]; // 交换位置
		L.r[j+dk] = L.r[0]; // 插入
		}
} //ShellInsert
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值