希尔排序(Shell's Sort)

希尔排序又叫缩小增量排序,是1959年 Shell 发明的第一个突破O(n2)的排序算法,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。

这种排序是把一定间隔的数当做一个数组,在每个分好的数组里进行插入排序,再缩小间隔重复步骤,直到间隔为1,直接插入排序所有数。

这样开始每组数据量都比较小,可以发挥插入的优势,排序速度比较快,在缩小间隔后,虽然个数增加,但是因为之前已经粗略排了序,有序性比较高,也能发挥插入的优势,提高效率。

那么这个间隔(增量)取多少比较好?

增量的取法有各种方案。最初 Shell 提出取 increment=n/2 向下取整,increment=increment/2 向下取整,直到 increment=1。但由于直到最后一步,在奇数位置的元素才会与偶数位置的元素进行比较,这样使用这个序列的效率会很低。后来 Knuth 提出取 increment=n/3 向下取整 +1 ,还有人提出都取奇数为好,也有人提出 increment 互质为好。应用不同的序列会使希尔排序算法的性能有很大的差异。 这里使用 n/3 向下取整 +1 的方法

举个栗子来理解:

01234567
1285714162

第一趟,取增量 increment  =  n/3 + 1 = 3,将数列划分为以 3 为间隔的数列(这里用同种颜色表示同一序列)

01234567
1285714162

在每个序列中进行插入排序

0

12

3

45

6

7

6

85

7

141

12

2
0

1

23

4

56

7

6

2

57

8

112

14

01

2

34

5

67
62

1

78

5

1214

第一趟结束后的排序

01234567
6217851214

再开始第二趟之旅,这次我们取增量为 increment = increment/3 + 1 = 2(都是向下取整),为了看得清咱一组一组来

0

1

2

3

4

5

6

7
6217851214

排序后结果

0

1

2

3

4

5

6

7

1

2

6

7

8

5

12

14

同样的,另一组排序

0

1

2

3

4

5

6

7

1

2

6

5

8

7

12

14

上面那个就是第二趟排序结果啦,最后第三趟排序,也就是增量为1(increment = increment/3 + 1 = 1),直接插入排序就可得到最终结果

0

1

2

3

4

5

6

7

1

2

5

6

7

8

12

14

主要代码

其实就是直接插入排序的外层多了个间隔 increment 的循环

void shell_sort(int a[], int n)
{
	int increment = n;
	do
	{
		increment = increment/3 + 1;
		for(int i=increment;i<n;i++)
		{
			int t = a[i];
			int flag = i-increment;
			while(flag>=0 && a[flag]>t)
			{
				a[flag+increment] = a[flag];
				flag -= increment;
			}
			a[flag+increment] = t;
		}
	}while(increment>1);
}

运行过程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值