希尔排序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;
}

仍有不足,欢迎交流。

猜你喜欢

转载自blog.csdn.net/qq_43685399/article/details/106722969