【插入排序】直接插入排序 与 希尔排序

这篇具有很好参考价值的文章主要介绍了【插入排序】直接插入排序 与 希尔排序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1. 排序的概念:

2.插入排序基本思想

3.直接插入排序

4.希尔排序


1. 排序的概念:

排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定。

内部排序:数据元素全部放在内存中的排序。

外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

2.插入排序基本思想

直接插入排序是一种简单的插入排序法,其基本思想是:

把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。

实际中我们玩扑克牌时,就用了插入排序的思想
【插入排序】直接插入排序 与 希尔排序,数据结构与算法,排序算法,算法,数据结构,c语言,插入排序

3.直接插入排序

直接插入排序(InsertSort),当插入第i(i>=1)个元素时,前面的array[0],array[1]...aray[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2.]..的排序码顺序进行比较,找到插入位置,即将array[i]插入,原来位置上的元素顺序后移

直接插入排序图解:

【插入排序】直接插入排序 与 希尔排序,数据结构与算法,排序算法,算法,数据结构,c语言,插入排序

代码实现思路:

假设在数组arr中,[0,end]这段区间是有序的,我们要将 end+1 位置处的元素插入,就需要将arr[end+1]与前面元素从后往前依次作比较,如果要排成升序,前面元素比arr[end+1]大的就往后移动,大或者等于就放在这个元素后面。数组一共有n个元素,要排n-1次,因为第一个元素不用排,从第二个元素开始。

代码:

//直接插入排序  升序
void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (a[end] > tmp)
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}
}

直接插入排序的特性总结:

  1. 元素集合越接近有序,直接插入排序算法的时间效率越高
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1),它是一种稳定的排序算法
  4. 稳定性:稳定

4.希尔排序

希尔排序法(ShellSort)又称缩小增量法。希尔排序法的基本思想是:先选定一个整数gap,把待排序文件中所有记录分成gap个组,所有距离为gap的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达gap==1时,所有记录已经在组内排好序

  1. 希尔排序是对直接插入排序的优化,因为直接插入排序处理接近有序的元素集合时,效率会很高,接近O(N)。
  2. 当gap >1时都是预排序,目的是让数组元素更接近于有序。当gap == 1时,就和直接插入排序相同了,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。

【插入排序】直接插入排序 与 希尔排序,数据结构与算法,排序算法,算法,数据结构,c语言,插入排序

代码实现思路:

我们先要实现预排序,使数组元素集合接近有序。我们先假设gap=3。实现预排序有两种方式,一种是分组排序,排好一组再排下一组,另外一种是多组并排。这两种方法内部还是直接插入排序。大家可以和上面直接插入排序的代码对比一下。

分组排序代码:

//预排序  一组一组预排,
void BeforeSort1(int* arr, int n)
{
	//假设gap = 3,分为3组,每组n/3个元素
	int gap = 3;
	for (int j = 0; j < gap; j++)
	{
        //每组内部进行排序
		for (int i = j; i < n - gap; i += gap)
		{
			int end = i;
			int tmp = arr[i + gap];
			while (end >= 0)
			{
				if (tmp < arr[end])
				{
					arr[end + gap] = arr[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			arr[end + gap] = tmp;
		}
	}
}

多组并排代码:可以对比一下上面代码。

//预排序 多组并排
void BeforeSort2(int* arr, int n)
{
	//假设gap = 3,分为3组,每组n/3个元素
	int gap = 3;

	for (int i = 0; i < n - gap; i++)
	{
		int end = i;
		int tmp = arr[i + gap];
		while (end >= 0)
		{
			if (tmp < arr[end])
			{
				arr[end + gap] = arr[end];
				end -= gap;
			}
			else
			{
				break;
			}
		}
		arr[end + gap] = tmp;
	}

}

其实:预处理不是简单的只处理一次,而是处理多次,让数据更加接近有序。最开始gap最大,之后gap每次逐渐减小,直至gap==1。

  • gap越大,大的数可以更快的到后面,小的数可以更快的到前面,数据越不接近有序
  • gap越小,大的小的数据挪动越慢,但是他越接近有序
  • gap == 1,就是直接插入排序

我们这里让gap=n   每次预排让 gap = gap/3+1,确保最后可以得到1。

希尔排序代码实现:对于gap的取法我们下面会讲到。

// 希尔排序  升序
void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > tmp)
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}

关系希尔排序的时间复杂度以及gap的取法问题

资料中是这样讲的:

《数据结构(C语言版)》--- 严蔚敏
【插入排序】直接插入排序 与 希尔排序,数据结构与算法,排序算法,算法,数据结构,c语言,插入排序《数据结构-用面相对象方法与C++描述》--- 殷人昆

【插入排序】直接插入排序 与 希尔排序,数据结构与算法,排序算法,算法,数据结构,c语言,插入排序

因为我们这里使用的gap是按照Knuth提出的方式取值的,而且Knuth进行了大量的试验统计,我们暂时时间复杂度就按照:O(N^1.25)到O(1.6 * N^1.25)来算。

稳定性:不稳定。

本篇结束!
【插入排序】直接插入排序 与 希尔排序,数据结构与算法,排序算法,算法,数据结构,c语言,插入排序文章来源地址https://www.toymoban.com/news/detail-637378.html

到了这里,关于【插入排序】直接插入排序 与 希尔排序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包