【排序】插入排序

一、直接插入排序:

1.基本思想:

依次将每个记录插入到一个有序的子序列中去,插入后该记录序列仍是有序的。


2.具体做法:

先将待排序的记录序列中的第一个记录看成是一个有序子序列,然后从第二个记录起逐个进行插入,直至整个记录序列变成按关键字非递减有序的序列为止。


3.举例:

初始关键字: 8     3     2     5     9    4    6

           i=1 : [ 8 ] 3   2      5    9     4    6

           i=2 : [ 3   8 ]  2      5     9    4    6

           i=3 : [ 2   3    8 ]    5     9    4    6

           i=4 : [ 2   3    5     8 ]    9    4    6

           i=5 : [ 2   3    5     8     9 ]    4    6

           i=6 : [ 2   3    4    5      8     9 ]     6

   排序结果: [ 2    3    4    5     6      8      9 ]


4.算法:

public void InsertSort(int a[], int n)
	/* 用直接插入排序法对a[0]~a[n-1] 排序 */
	{
		int i, j;
		int temp;
		for (i = 1; i < n; i++) {
			temp = a[i]; /* 将要插入的记录暂存到temp 中 */
			j = i - 1; /* 从有序子序列的最高位开始比较 */
			while (j >= 0 && temp < a[j]) {
				a[j + 1] = a[j]; /* 将关键字>temp的记录后移 */
				j--;
			}
			a[j + 1] = temp; /* 插入到正确位置 */
		}
	}


5.算法分析
辅助空间:O(1)
时间:
(1)关键字的比较次数
最好(“ 正序” ): n-1

最坏(“ 逆序“): n(n-1) / 2

(2 )记录的移动次数
开始时,将要插入的记录→temp ,移动1,最后,将记录插入适当位置,即 temp →a[j+1]  ,移动1次。比较后,若temp.key<a[j].key ,则 a[j] →a[j+1]

最小移动量(“正序”时):2(n-1)

最大移动量(“逆序”时):(n-1)(n+4)/ 2

∴ 直接插入排序的 时间复杂度 为O(n^2)


二、折半插入排序

1.基本思想:

先将待排序的记录序列中的第一个记录看成是一个有序子序列,然后从第二个记录起依次将每个记录插入到一个有序的子序列中去,插入后该序列仍是有序的。但在查找插入位置时,不是采用顺序查找,而是采用折半查找。


2.算法:

public void BInsertSort(int a[], int n)
	/* 用折半插入排序法对a[0]~a[n-1] 排序 */
	{
		int i, j, low, high, mid;
		int temp;
		for (i = 1; i < n; i++) {
			temp = a[i]; /* 将要插入的记录暂存到temp 中 */
			low = 0;
			high = i - 1;
			while (low <= high) /* 在有序子序列中折半查找插入位置 */
			{
				mid = (low + high) / 2;
				if (temp < a[mid])
					high = mid - 1;
				else
					low = mid + 1;
			}
			for (j = i - 1; j > high; j--)
				a[j + 1] = a[j]; /* 将关键字>temp 的记录后移 */
			a[high + 1] = temp; /* 插入 */
		}
	}
注:折半查找是先比较找到位置然后一起移动,因此比较次数并不比直接插入少。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值