排序(3) -- (直接)插入排序

之所以標題加上"(直接)"的字眼, 是因爲有許多時間複雜度爲更低的算法都是對這個最原始/直接的插入排序算法優化演變出來的. 所以他們也可以算是插入排序. 當然, 這裏我們要說的是最原始最直接的插入排序.


插入排序: O(n ^ 2)

插入排序(InsertSort)的基本思想是:每次從無序表中取出第一個元素,把它插入到有序表的合適位置,使有序表仍然有序。第一趟比較前兩個數,然後把第二個數按大小插入到有序表中; 第二趟把第三個數據與前兩個數從後向前掃描,把第三個數按大小插入到有序表中;依次進行下去,進行了(n-1)趟掃描以後就完成了整個排序過程。插入排序類似玩牌時整理手中紙牌的過程。
插入排序是穩定的排序方式. 

代碼如下:
PS: 其實是昨晚寫的, 今天整理出來. 半夜實在頭昏腦漲, 寫了三遍, 才最終演化成最後那種稍好的形式...
for (i = 1; i < n; i++) //從1到n-1, 往前面插
{
	temp = a[i]; //要插入的值爲a[i]
	for (j = i; j > 0; j--); //從a[i-1]開始依次往前比較
	{
		if (temp >= a[j-1]))
		{
			break;
		}
	}

	if (j < i) //則a[j]的位置就是a[i]需要插入的地方, a[j]...a[i-1]先依次往後移
	{
		for (k = i; k > j; k--)
		{
			a[k] = a[k-1]
		}
		a[j] = temp;
	}
}

看了眼標準的算法實現, 發現醜爆了, 而且確實麻煩了, 沒必要先找出位置, 
再移動. 可以一邊找就一邊移動了, 就不用費二遍事了.

遂改成了下面這樣..
for (i = 1; i < n; i++) //從1到n-1, 往前面插
{
	temp = a[i]; //要插入的值爲a[i]
	for (j = i - 1; (j >= 0) && (temp < a[j]); j--) //從a[i-1]開始依次往前比較
	{
		swap(temp, a[j]);
	}
}
仔細和標準的算法實現對比了下, 發現這種實現像冒泡, 不是插入..
效率上來說一個swap是三個語句, 效率確實還是低
遂進一步修改成了最終版..
for (i = 1; i < n; i++) //從1到n-1, 往前面插
{
	temp = a[i]; //要插入的值爲a[i]
	for (j = i; (j > 0) && (temp < a[j-1]); j--) //如果temp比a[j-1]小, 則a[j-1]的值向後移動一個單位.
	{
		a[j] = a[j-1];
	}
	a[j] = temp;
}

總結: 插入排序, 相當於待插入元素是遊離於"隊伍"外面, 看到比自己大的, 就讓其後退一步, 直到找到合適自己的位置, 直接站進隊伍裏. 上面第二種實現 , 相當於待插入元素是在隊裏裏面, 拍拍前面人的肩膀, "嗨, 哥們, 你太高了, 咱倆換下位置, 你站我後面去." 這個依次交換的方式顯然是冒泡的方式了, 插入, 不是"交換", 而是"移動", 最後一錘定音, 插進去! ^ ^

發佈了25 篇原創文章 · 獲贊 6 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章