希尔排序C++实现(附完整可运行源代码)

希尔排序(Shell)

  1. 思想:将数组元素分成若干组,每组分别进行插入排序,使整个数组逐渐变成部分有序数组,再慢慢减少所分的组数,最终合并成一个组 。
  2. 较于插入排序的优化原理:普通插入排序对少量数据效率高;普通插入排序对越有序的数据效率越高;
  • 希尔排序中先分组即是将大数组分成若干小数组,此时进行普通插入排序效率高;
  • 在慢慢减少分组时,大量无序数据已逐渐变成部分有序数据,此时就算是大量的数据,进行普通插入排序效率依旧高。
  1. 优缺点:能够用于大量无序的数据,但是不稳定 。
  2. 复杂度:平均时间复杂度:O(nlogn)、最好:O(nlogn),最坏:O(n)
    不需要额外的辅助空间。
  3. 稳定性:不稳定

源代码

  • 以下是合并在一起的写法
/****************************************
 题目:希尔排序 (优化后的插入排序)
	- 将数组分成group组元素(在逻辑上进行分组);
	- 其中i与i+group为同一组,其他组以此类推;
	- 然后每一组都分别进行插入排序;
	- 再不断缩小组数,直到组数为0
 ****************************************/
//参数:
//		numbers[]:数组
//		length:数组长度
void Shell(int numbers[], int length)
{
	//1. 判断传入的参数是否有效
	if (numbers == nullptr || length <= 0)
		return;

	int j = 0;
	int temp = 0;			//临时变量
	int group = length / 2;	//第一次分的组数,每组最多两个元素

	//2. 组数不为0时循环
	while (group >= 1)
	{
		//3. 以下即为普通插入排序,group用于获取每组的元素
		//	 外层循环代表每组插入的轮次,每轮的结果都是:将后面的数据插入前面的有序序列中
		for (int i = group; i < length; ++i)
		{
			//4. 暂存有序序列后面的一个元素作为需要插入的元素
			//	 第一轮时,将下标为0的元素看作有序序列,将下标为0+group的同组元素暂存准备进行插入
			temp = numbers[i];
			//5. 内层循环完成元素的移动(当数列有序时,内层循环只运行一次就break了,总的时间复杂度就会变成O(n))
			for (j = i - group; j >= 0; j -= group)
			{
				//6. 如果要插入的元素大于或等于有序序列中的某一个元素,说明要插入的元素的位置就在这个元素后面
				if (numbers[j] <= temp)
					break;
				//7. 未找到插入位置则将元素依次往后移动
				numbers[j + group] = numbers[j];
			}
			//8. 将要插入的元素放在找到的位置
			numbers[j + group] = temp;
		}
		//9. 将组数减半继续插入排序
		group = group / 2;
	}
}
//简单测试
int main()
{
	const int length = 7;
	int numbers[length] = { 3, 2, 7, 11, 9, 4, 2 };

	Shell(numbers, length);

	for (int i = 0; i < length; i++)
		cout << numbers[i] << "  ";

	cout << endl;
	return 0;
}
  • 以下是分成两个函数的写法,详细注释我就不写了,一样理解就行
void InsertSort_s(int[], int, int);		//插入排序函数的声明
//希尔排序
void Shell(int numbers[], int length)
{
	//1. 判断传入的参数是否有效
	if (numbers == nullptr || length <= 0)
		return;

	int group = length / 2;	//第一次分的组数,每组最多两个元素
	//2. 组数不为0时循环
	while (group >= 1)
	{
		//3. 以下即为普通插入排序,group用于获取每组的元素
		InsertSort_s(numbers, length, group);
		//4. 将组数减半继续插入排序
		group = group / 2;
	}
}
//配套的插入排序
//注:当group = 1时,即为普通的插入排序,可以直接调用
void InsertSort_s(int numbers[], int length, int group)
{
	int j;
	int temp;	//临时变量

	for (int i = group; i < length; ++i)
	{
		temp = numbers[i];
		for (j = i - group; j >= 0; j -= group)
		{
			if (numbers[j] <= temp)
				break;

			numbers[j + group] = numbers[j];
		}
		numbers[j + group] = temp;
	}
}
//简单测试
int main()
{
	const int length = 12;
	int numbers[length] = { 3, 2, 7, 11, 9, 4, 2, 10, 14, 19, 15, 21 };

	Shell(numbers, length);

	for (int i = 0; i < length; i++)
		cout << numbers[i] << "  ";

	cout << endl;
	return 0;
}

仍有不足,欢迎交流。

  • 0
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值