【複習】插入排序

插入排序

這麼多插入排序,由直接插入排序進行變化得來!

直接插入排序 [穩定]

  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=1n1\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. 基本排序算法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章