十大排序之『插入排序』(直接、折半、希尔排序)

**先贴上经典总结图在这里插入图片描述
**

一、插入排序(直接法+折半优化)

原理:类比扑克牌理牌原理,将未排序序列中的元素一个个插入到已排序序列的正确位置上。
直接法:在有序序列中一个个比较,寻找正确位置
折半优化就是:运用二分法找到正确的插入位置
注意:插入排序一般会设置0号位置为哨兵位,不但可以临时保存元素,越界时还可以直接返回。所以数组是从1开始

void InsertSort(vector<int>& a,int n) {//直接插入排序 
	int i, j;
	for (i = 2;i <= n;i++) {//0是哨兵项,从第二个元素起开始遍历插入
		if (a[i] < a[i-1]) {//需要排序再进行操作
			a[0] = a[i];//复制为哨兵
			for (j = i - 1;a[0] < a[j];j--) {
				a[j+1] = a[j];//将数组后移
			}
			a[j+1] = a[0];//插入到正确的位置,上一个移走后,j--了,所以这里是j+1
		}
	}
}
void BlnsertSort(vector<int>& a,int n) {//折半插入排序
	int i, j;
	for (i = 2;i <= n;i++) {
		a[0] = a[i];//将当前元素存储到哨兵位置
		int low = 1, high = i - 1;
		while (low <= high) {//二分法查找插入位置
			int mid = (low + high) / 2;
			if (a[0] > a[mid]) low = mid + 1;
			else high = mid - 1;
		}//循环结束,high+1为插入位置
		for (j = i - 1;j >= high+1;j--) {//移动元素,挪出位置
			a[j+1] = a[j];
		}
		a[high+1] = a[0];
	}
}

二、希尔排序

原理:易知插入排序在数列有序度较高的情况下时间复杂度较低(可降至O(n)),基于此,希尔排序的思想是:先将待排序序列分割为若干个子序列,分别进行直接插入排序,待整个数列基本有序,再对全体序列进行一次直接插入排序。
子序列的分割用到了增量序列,增量序列是一组递减并且互质的数,并且最后一个数一定是1,对于t趟的希尔排序,增量序列可以是dlta[k]=2^(t-k+1)-1。值得一提的是,目前希尔排序的最优增量序列仍是数学界尚未解决的难题。
按照dlta[k]进行t趟排序,每一趟对于数列中所有相隔距离为dlta[k]的元素进行排序

void ShellInsert(vector<int>& a, int dk,int n) {
	//间隔dk,作一趟插入排序,相较于直接插入排序做了以下修改:
	//1.前后记录位置的增量是dk,而不是1
	//2.r[0]只是暂存单元,不是哨兵,当j<=0时,插入位置已找到
	int i, j;
	for (i = dk + 1;i <= n;i++) {//相距dk,所以从dk+1开始,
	//寻找元素插入到前面的一个元素中
		if (a[i] < a[i-dk]) {
			a[0] = a[i];
			for (j = i - dk;j > 0 && (a[j] > a[0]);j -= dk) {
				a[j+dk] = a[j];
			}
			a[j+dk] = a[0];
		}
	}
}
void ShellSort(vector<int>& a, int dlta[], int t,int n) {//n为数组元素个数,0号作为哨兵,数组空间为n+1
	//按增量序列dlta[0…t-1]对顺序表L作希尔排序
	for (int k = 0;k < t;k++) {
		ShellInsert(a, dlta[k], n);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值