# 2. 插入排序

基本思想:将一个元素记录按其应用的位置插入
到已排好序的序列中。依据寻找插入位置的方法不同,插入排序分为:
直接插入排序;折半插入排序;希尔插入排序;表插入排序。

# 1. 直接插入排序

基本思想
插入 Ri 时,R1,R2,…,Ri-1 已排好,用 Ri 的关键字与 Ri-1,Ri-2,…,R1 比较,找到插入位置。即把一个记录插入到已排好序的有序表中。

/* 对记录数组 r 做直接插入排序,length 为数组中待排序记录的数目 */
void InsSort(RecordType r[], int length){
	for ( i=2 ; i<=length ; i++ ){
		r[0]=r[i]; j=i-1; /* 将待插入记录存放到监视哨 r [0] 中 */
		while (r[0].key< r[j].key ){ /* 寻找插入位置 */
			r[j+1]= r[j]; j=j-1;
	 	}
		r[j+1]=r[0]; /* 将待插入记录插入到已排序的序列中 */
	}
} /* InsSort */

性能分析
时间复杂度 O(n2)
空间复杂度 O(1)
稳定

# 2. 折半插入排序

(二分法插入排序)
基本思想:
设在顺序表中有一个记录序列 R [1], R [2], …, R [n]。其中,R [1], R [2], …, R [i-1] 是已经排好序的记录。在插入 R [i] 时,利用折半搜索法寻找 R [i] 的插入位置。

/* 对记录数组 r 进行折半插入排序,length 为数组的长度 */
void BinSort (RecordType r[], int length){
	for ( i=2 ; i<=length ; ++i ){
		x= r[i];
		low=1;
        high=i-1;
		while (low<=high ){ /* 确定插入位置 */
            mid=(low+high) / 2;
		 	if ( x.key< r[mid].key ) high=mid-1;
			else low=mid+1;
		}
		for ( j=i-1 ; j>= low; --j ) r[j+1]= r[j]; /* 记录依次向后移动 */
		r[low]=x;
		/* 插入记录 */
	}
}/*BinSort*/

性能分析:
时间复杂度 O(nlog2n)
空间复杂度 O(1)
稳定

# 3. 希尔排序

基本思想
先将待排序记录序列分割成若干序列,分别进行直接插入排序;待整个序列中的记录基本有序后,再全体进行一次直接插入排序。

image-20200528222245716

/* 对记录数组 r 做一趟希尔插入排序,length 为数组的长度,delta 为增量 */
void ShellInsert(RecordType r[], int length, int delta){
	for(i=1+delta ;i<= length; i++) /* 1+delta 为第一个子序列的第二个元素的下标 */
		if(r[i].key < r[i-delta].key){
			r[0]= r[i]; /* 备份 r [i] (不做监视哨) */
			for(j=i-delta; j>0 &&r[0].key < r[j].key ; j-=delta)
				r[j+delta]= r[j];
				r[j+delta]= r[0];
			}
}/*ShellInsert*/
/* 对记录数组 r 做希尔排序,length 为数组 r 的长度,delta 为增量数组,n 为 delta [] 的长度 */
void ShellSort(RecordType r[], int length, int delta[], int n){
	for(i=0 ; i<=n-1; ++i) 
	    ShellInsert(r, Length, delta[i]);
}

性能分析:
时间复杂度 O(n^1.5)
空间复杂度 O(1)
不稳定

-->