排序算法(四)--谢尔排序(缩小增量排序)

由上一篇博文可知,冒泡排序时,若待排序序列长度为n,则冒泡排序法时间复杂度为O(n2)。但若待排序序列已经按值有序,则其时间复杂度变为O(n)。由此推想,若待排序序列按值“基本有序”,则冒泡排序法的效率可以明显提高,从另一方面来看,冒泡排序法基本原理较简单。谢尔排序法正是从以上两点对冒泡排序法进行改进得到的。

核心思想

首先确定一个元素间隔数gap(也称增量),然后将参加排序的序列按此间隔数从第一个元素开始一次分为若干个子序列,即分别将所有位置相隔为gap的元素视为一个子序列,在各个子序列中采用某种排列方法进行排序(这里采用冒泡排序法);然后减小排列间隔,并重新将整个序列按新的间隔数分成若干个子序列,再分别对各个子序列进行排序,重复以上步骤,直到间隔数gap=1。

主要特点

对于排序的每一趟以不同的的间隔数对子序列进行排序,因而元素的移动在子序列之间跳跃进行。gap越大,跳跃的跨度就越大。很多情况下,当gap=1时,序列几乎已经按值有序,不需要进行较多元素的移动就能达到排序目的。

举例
趟序间隔数排序结果
位数12345678
初始4938659776132749'
第1趟gap1=449132749'76386597
第2趟gap2=2271349386549'7697
第3趟gap3=11327384949'657697

初始时,我们按照gap=4进行划分,则可以分4个子序列,上面表格中相同颜色的格子代表一个子序列。在每个子序列中,所有数值间进行冒泡排序。这里因为每个子序列中只有两个数值,故按照冒泡排序,只需要按大小对两个数值进行交换即可。经过第一趟排序,得到排序结果见表格。再使gap=2,得到第二趟排序结果,依次进行直到gap=1.例子中由于数值较少,故只进行3趟排序就得到了想要的结果。
注意
gap值的选取方法不是固定的,常用方法是每次gap值为上一次的一半,向下取整。

代码

约定:

  1. 假设数据中有n个数据元素(关键字)。排列算法中,将序列中各关键字值依次存放于类型为keytype的数组元素K[1], K[2], K[3], …, K[n]中。
  2. 排序结果按照数据元素(关键字)值的大小,从小到大排序。
void SHELLSORT(keytype K[], int n)
{
	int i, j, flag, gap = n;
	keytype temp;
	while ( gap > 1 ) {
		gap = gap / 2;
		do {
			flag = 0;
			for ( i=1 ; i<=n-gap ; i++ ) {
				j = i + gap;
				if ( K[i] > K[j] ) {
					temp = K[i];
					K[i] = K[j];
					K[j] = temp;
					flag = 1;
				}
			}
		} while ( flag != 0 );
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值