【复习】插入排序

插入排序

这么多插入排序,由直接插入排序进行变化得来!

直接插入排序 [稳定]

  1. 将序列划分为两块:有序区,无序区
  2. 初始态序列 有序区R[0],无序区R[1] ~ R[n-1]

步骤

  1. i 指向无序区的头j 指向有序区的尾tmp 用于临时储存待插入的值
  2. 无序区中每次拿出第一个元素插入到有序区,一共可以执行 n - 1 次(1 ~ n - 1)
  3. 拿出R[i] 存入tmp临时变量j = i - 1 从有序区的尾部开始扫描,大于 tmp 的元素向后移位一个(R[i]已经用tmp临时储存,可以直接覆盖)
  4. 直到扫描到一个比tmp小的,将tmp插入到该位置的后面,即 j+ 1 的位置
  5. 整个过程中, j 满足 j >= 0
    在这里插入图片描述

实现

void insertSort(int *R,int n){
	//param: R 序列
	//param: n 序列长度
	int i,j,tmp;
	for(i=1;i<n;i++){
		if(!(R[i] < R[i-1]))
			continue;//此元素不需要排序
		tmp = R[i];
		for(j=i-1;j>=0;j--){
			if(R[j]<tmp)
				break; //找到该元素
			else
				R[j + 1] = R[j];
		}
		R[j + 1] = tmp;//插入到J后,这个放在外面是因为,有可能插入在第一个位置,即j = -1的时候;
	}
}

分析

当原序列为 正序

每一轮:只进行一次比较,即 R[i - 1] < R[i]的比较,不发生元素的移动。
Cmin = n - 1
Mmin = 0

当原序列为 逆序

每一轮:有序区的所有元素都需要进行一次,即需要 i 次比较,元素发生移动的个数 (i - 1 - 0) + 1,另外对于临时变量 tmp两次 额外的移动,总计 i + 2 次移动
Cmax = n(n-1)/2 = O(n2)
Mmax = (n-1)*(n + 4) / 2 = O(n2)

平均时间复杂度

每一轮:平均比较次数 (1+i )/ 2 ,平均移动次数 (0 + i) / 2 + 2
总的比较次数和移动次数 = (n - 1)(n + 4)/2 = O(n2)

折半插入排序 [稳定]

步骤

  1. 其步骤和直接插入相似,只是先用二分法找到插入的位置,再进行元素移动

实现


void binInsertSort(int *R,int n){
	int i,j,tmp;
	int low,high,mid;
	for(i=1;i<n;i++){
		if(!(R[i] < R[i - 1]))
			continue;
		tmp = R[i];
		low = 0;high = i - 1;
		while(low <= high){
			mid = (low + high)/2;
			if(tmp < R[mid])
				high = mid - 1;
			else
				low = mid + 1;
		}
		
		for(j = i - 1; j >= high + 1;j--){
			R[j + 1] = R[j];
		}
		R[high + 1] = tmp;
	}
}

分析

平均比较:log2(i+1)
平均移动:i/2 + 2
平均时间复杂度: i = 1 n 1 \sum_{i = 1}^{n-1} (log2(i+1) + i/2 + 2) = O(n2)

希尔排序 [不稳定]

  1. 增量分块,增量递减
  2. 分组的直接插入排序

与直接插入排序想比,比较每次跳跃d,初始值从d开始。

步骤

取一个d,分为d组,d递减至1
在这里插入图片描述

实现

void shellSort(int * R,int n){
	int i,j,tmp,d;
	d = n  / 2;
	while(d > 0){
		for(i = d; i < n;i++) //R[d]是第一组的第二个元素(直接插入法中将R[0]作为初始有序区)
		{
			tmp = R[i];
			for(j = i-d;j>=0&&tmp<R[j]; j-=d){
				R[j+d] = R[j];
			}
			R[j+d] = tmp; //插入在后面
		}
		d = d/2;
	}
}

分析

每走一趟,d 变为 floor(d/2)
走了 t = floor(log2n) - 1 次(-1 是因为d的初始值就为 n/2),d = 1,再走一次进入直接插入排序,完成所有的排序
平均时间复杂度:O(n1.3)

不稳定性

在这里插入图片描述
希尔排序是分组的,移动跨越很大,过程中不一定是有序的,当 d=1 且执行完 的时候为有序。

参考

  1. 深入理解希尔排序
  2. 基本排序算法
发布了23 篇原创文章 · 获赞 33 · 访问量 3235

猜你喜欢

转载自blog.csdn.net/shipsail/article/details/103513988
今日推荐