插入/希尔排序

1 插入排序

1.1 基本思想

把待排序的,插入到已经排好序的合适的位置。
在这里插入图片描述

边插入边排序,保证子序列都是排好序的。

1.2 基本操作

在这里插入图片描述
在这里插入图片描述

1.3 插入位置

在这里插入图片描述
Q:如何找到插入位置?
A:下方的插入排序方法将会介绍。

2 插入排序的种类

在这里插入图片描述

2.1 直接插入排序

采用顺序查找法查找插入位置。
在这里插入图片描述
循环跳出条件为:j >= 0 && x < a[j]
从后往前找,但有个问题,每次循环都要判断两个,时间太久,之前在顺序查找法的时候,有个带哨兵的,现在可以用上。直接把待插入元素第i个位置上的元素放到下标为0的位置(哨兵位置)上面。
在这里插入图片描述

2.1.1 直接插入排序算法

void InsertSort(SqList &L)
{
	int i, j;
	for (i = 2; i <= L.length(); ++i)
	{
		if (L.r[i].key < L.r[i-1].key)//若"<",需要将L.r[i]插入到有序子表
		{
			L.r[0] = L.r[i];//复制2为哨兵,减少循环的比较条件
	for (j = i-1; L.r[0].key < L.r[j].key; --j)
			{
				L.r[j+1] = L.r[j];//记录后移
			}
			L.r[j+1] = L.r[0];//插入到正确的位置
		}
	}
}

2.1.2 性能分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.1.3 结论

在这里插入图片描述

2.2 折半插入排序

直接插入法是在查找位置的时候,从后往前依次进行比较的,这种一个一个进行比较的方法叫做顺序查找法。折半查找法定义一个low端一个high端,找到mid中间位置,与哨兵位置比较,mid比哨兵小,就在右半区域进行查找;反之亦然。找到后依然是要将位置向后移动,然后将哨兵位置的元素放到合适的位置。

2.2.1 折半插入排序算法

void BInsertSort(SqList &L)
{
	for (i = 2; i <= L.length(); ++i)//依次插入第2~第n个位置
	{
		L.r[0] = L.r[i];//当前插入元素存到哨兵位置
		low = 1;
		high = i-1;//采用二分查找法查找插入位置
		while(low <= high)
		{
			mid = (low + high) / 2;
			if (L.r[0].key < L.r[mid].key)
			{
				high = mid - 1;
			}
			else 
			{
				low = mid + 1;
			}
		}//循环结束,high+1则为插入位置
		for (j = i-1; j >= high+1; --j)
		{
			L.r[j+1] = L.r[j];//移动元素
		}
		L.r[high+1] = L.r[0];//插入到正确的位置
	}
}

2.2.2 性能分析

在这里插入图片描述
在这里插入图片描述

折半只是减少了比较的次数,移动的次数没有减少。

2.3 希尔排序

在这里插入图片描述
希尔排序算法的出发点,就是怎么能够在进行插入排序的时候基本有序,怎么能比较一次就移动一大步,相当于是继承了上方几种排序的优点。

基本思想:
先将整个待排记录序列分割成若干子序列(元素个数就少了,交换的时候可以移动一大步),分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。

希尔排序算法,特点:

  • 缩小增量
  • 多遍插入排序

在这里插入图片描述

思路:
在这里插入图片描述
最后一次是1间隔的插入排序。

特点:

在这里插入图片描述

2.3.1 希尔排序算法

//主程序
void ShellSort(SqList &L, int dlta[], int t)
{
//按增量序列dlta[0...t-1]对顺序表L作希尔排序
	for (k=0; k<t; ++k)
	{
		ShellInsert(L, dlta[k]);//一趟增量为dlta[k]得到插入排序,总共是循环的t趟
	}
}
//其中一趟的排序操作
void ShellInsert(SqList &L, int dk)
{
	for (i=dk+1; i<=L.length(); ++i)
	{
		if (r[i].key < r[i-dk].key)
		{
			r[0] = r[i];
for (j=i-dk; j>0 && (r[0].key<r[j].key);j=j-dk)
			{
				r[j+dk]=r[j];
			}
			r[j+dk] = r[0];
		}
	}
}

本质上还是插入排序,但是按照间隔来的。

2.3.2 性能分析

在这里插入图片描述
在这里插入图片描述
非稳定性算法
在这里插入图片描述

2.3.3 结论

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值