0
点赞
收藏
分享

微信扫一扫

【十大经典排序详解_希尔排序】

mjjackey 2022-01-20 阅读 106

希尔排序

希尔排序可以说是插入排序的一种变种。无论是插入排序还是冒泡排序,如果数组的最大值刚好是在第一位,要将它挪到正确的位置就需要 n - 1 次移动。也就是说,原数组的一个元素如果距离它正确的位置很远的话,则需要与相邻元素交换很多次才能到达正确的位置,这样是相对比较花时间了。

希尔排序就是为了加快速度简单地改进了插入排序,交换不相邻的元素以对数组的局部进行排序。

希尔排序的思想是采用插入排序的方法,先让数组中任意间隔为 h 的元素有序,刚开始 h 的大小可以是 h = n / 2,接着让 h = n / 4,让 h 一直缩小,当 h = 1 时,也就是此时数组中任意间隔为1的元素有序,此时的数组就是有序的了。

为方便理解我还准备了图片:
在这里插入图片描述
下面是图解 _思路:

首先它把较大的数据集合分割成若干个小组(逻辑上分组),然后对每一个小组分别进行插入排序,此时,插入排序所作用的数据量比较小(每一个小组),插入的效率比较高
在这里插入图片描述

下面有颜色的是逻辑上的分组,并没有实际地进行分组操作,在数组中的位置还是原来的样子,只是将他们看成这么几个分组(逻辑上分组)

可以看出,他是按下标相隔距离为4分的组,也就是说把下标相差4的分到一组,比如这个例子中a[0]与a[4]是一组、a[1]与a[5]是一组…,这里的差值(距离)被称为增量

在这里插入图片描述
每个分组进行插入排序后,各个分组就变成了有序的了(整体不一定有序)

在这里插入图片描述
此时,整个数组变的部分有序了(有序程度可能不是很高)

在这里插入图片描述
然后缩小增量为上个增量的一半:2,继续划分分组,此时,每个分组元素个数多了,但是,数组变的部分有序了,插入排序效率同样比较高
在这里插入图片描述
同理对每个分组进行排序(插入排序),使其每个分组各自有序
在这里插入图片描述
最后设置增量为上一个增量的一半:1,则整个数组被分为一组,此时,整个数组已经接近有序了,插入排序效率高
在这里插入图片描述
同理,对这仅有的一组数据进行排序,排序完成

希尔排序的精华:同时构造出两个特殊条件以达到高效插入

代码:

 void shellSortCore(vector<int>& nums, int gap, int i)
{
	int inserted = nums[i];
	int j;
	//插入的时候按组进行插入
	for (j = i - gap; j >= 0 && inserted < nums[j]; j -= gap)
	{
		nums[j + gap] = nums[j];
	}
	nums[j + gap] = inserted;
}

void shellSort(vector<int>& nums)
{
	int len = nums.size();
	//进行分组,最开始的时候,gap为数组长度一半
	for (int gap = len / 2; gap > 0; gap /= 2)
	{
		//对各个分组进行插入分组
		for (int i = gap; i < len; i++)
		{
			//将nums[i]插入到所在分组正确的位置上
			shellSortCore(nums, gap, i);
		}
	}

	for (auto a : nums)
	{
		cout << a << " ";
	}
}
举报

相关推荐

0 条评论