排序算法---插入排序--直接插入排序

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

稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
内部排序:数据元素全部放在内存中的排序。
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序(在硬盘中)。

注:以下排序均为升序排列;

一 、插入排序 -- 直接插入排序

排序思想:从每个序列的第二个数开始,依次向前插入,使得插入后的数列依旧有序,直到最后一个数停止;

具体过程如下图:

过程分析:

第一步: 因为第一个数一定是有序的,所以我们可以从第二个数开始向前插入;

第二步: 第二个数插入后,前两个数肯定是有序的,此时我们可以取后面的数依次向前插入,使得每次插入时,前n个数为有序数列,直到最后一个数插完;

插入过程: 1.令有序数列的后一个元素标定为tmp, 同时用end 记录有序数列的最大下标;

                   2.开始遍历有序数列,如果tmp < a[end] (设有序数列的首元素地址为a); 就把a[end] 处的元素向后覆盖(即令a[end + 1] = a[end] ) 同时--end ,向前移动寻找比tmp小或者相等的元素;

                  3.如果找到后就把end+1 位置的元素修改成tmp即可,特殊情况:(若end < 0 直接插到 0 的位置,若tmp 比前面的数都大,直接插到最后,end 不用动);

插入示例图:

代码如下:(这里建议读者应从单趟排序开始写,比较容易控制,在后面写一些复杂排序时能形成习惯,减少出错的概率)

void InsertSort(int* a, int numsize)
{
	for (int i = 0; i < numsize - 1; i++)//如果不用i < numsize - 1; 下面的a[end + 1] 会越界
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				--end;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;//当tmp要插到头元素时,此时end == -1,end + 1 == 0 刚好为首元素下标;
	}
}

时间复杂度:O(N ^ 2);

最好的情况:O(N) (在所有数均有序的情况下)

稳定性:插入排序是稳定的内排序

补充:与冒泡排序相比其实插入效率会更高,虽然他们的时间复杂度都为O(N^2),举个例子证明: 假如有一组大小为 9 的整体无序的整型数组,冒泡的遍历次数就是 8!但是插入排序每次可能只要挪动一两次前 n 个数就有序了,只有在最坏的情况下才会到8!次,所以在绝大部分情况下插入排序的效率是比冒泡高的,当然不排除有特殊情况;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值