shell排序(C++)

希尔排序的本质是对插入排序的优化,如果对插入排序记不太清了,可以去看下我的这篇文章,链接如下:https://blog.csdn.net/ICer_WangV/article/details/122527449?spm=1001.2014.3001.5502

插入排序算法,由于需要将待排序的数据和数组中的元素从后往前比较,然后插入数组当中。那么最坏的情况就是插入的元素是最小的,这就需要将原有的元素都后移(每次插入都需要将数组遍历一次),这就造成插入排序算法有较高的时间复杂度。

那么我们来举个例子讲一下如何去优化:

现在有一个待排数组:

我们首先引入一个概念,叫做“步长”,以步长为间隔,将待排数组进行分组,初始步长通常为为:数组元素个数 /2。这里共有10个元素,则步长为5。将待排数组以5为间隔,分为如下5组:

然后将这五个组,视为5个含有两个元素的待排数组,在组内进行插入排序。 

 然后,再将步长设为4,重新分为4组(注意看颜色变化)

同样的,再将这四组数据进行插入排序

 以此类推,步长为3,分为三组,插入排序

步长为2,分为两组

最后,步长为1,进行最后一次排序,就得到了一个有序的数组

整个的排序的过程如下:

做个总结:初始步长设为元素个数/2,每次排序后,步长递减,。每次排序都以步长为间隔给所有元素分组,组内做插入排序。

这样优化后,插入排序时需要后移的元素(或者说需要遍历的元素)就少了很多,以此降低时间复杂度 ,优化过的算法即为shell算法。

代码实现:

#include<iostream>
using std::cout;
using std::endl;
void traverse(int* a, int n);
void shell_sort(int a[], int len);
int main()
{
	int a[9] = { 23,45,65,12,43,9,87,98,76 };
	traverse(a, 9);
	cout << endl;
	shell_sort(a, 9);
	traverse(a, 9);
	return 0;
}
void shell_sort(int a[],int len)
{
	int step;
	int value;
	int i;
	int j;
	for (step = len / 2; step > 0; step--)
	{
		for (i = 0; i < len - 1; i++)
		{
			value = a[i + 1];
			for (j = i + 1; j >= 0 && value < a[j - 1]; j -= step)    //插排
			{
				a[j] = a[j - step];    
			}
			a[j] = value;   
		}
	}
}
void traverse(int* a, int n)
{
	for (int i = 0; i < n; i++)
		cout << a[i] << " ";
}

核心代码那里和插排有点相似,分组是通过 j -= step来实现的。最初的想法是创建vector动态数组,用来存储每个分组的元素,但是太过复杂了,通过学习,发现在插排上面做一些改动,代码实现简单,还好理解。

运行结果如下:

 

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值