1. 程式人生 > 其它 >1035 插入與歸併 (25 point(s))

1035 插入與歸併 (25 point(s))

判斷是插入還是歸併函式。題目所說“保證每組測試的結果是唯一的”,所以判斷其中一個即可。而判斷插入函式,由於插入排序必然使得

所以插入排序滿足前面的元素有序,而後面的元素待排元素與原始序列相等。所以由以下程式碼來判斷。

a[j] == b[j]

if(j == n)

當後面待排元素和原始序列都滿足相等的條件,那麼就可以用 j == n 來判斷為插入排序。


sort(a, a + i + 2);

當時想了半天為什麼這裡要+2。對於插入排序來說,再迭代一輪就將已排序末尾的後一個未排序元素拉進來。而前面由

for (i = 0; i < n - 1 && b[i] <= b[i + 1]; i++);

給出了已排序元素的下標位置。但是下標 i 與後一個元素相差1。而 sort 是 sort (first, last) 對 [first, last) 範圍內的元素進行排序範圍內排序,不包括 last 所以要在下一個待排序元素的下標 i + 1 基礎上再 + 1。

以前都是 (a, a + n) 直接 + n 的,忽略了這樣用的真正原因是什麼。

同時這裡還學到,當有某些部分不理解的時候,需要將這部分裡面的細節拆開理解。比如前面的 sort 裡有一個 i,當時不理解這個 i 是幹什麼的。所以就用了 cout 將這個 i 及其它對應的元素打印出來。這才知道這個東西在這裡具有什麼意義。


int k = 1, flag = 1;

k 是每次歸併排序時,組的元素的個數,初始化為 1每一次進入迴圈時會對組的個數加倍。加倍後再進行歸併和排序。

k *= 2;

for(i = 0; i < n; i++)
	if(a[i] != b[i])
		flag = 1;

flag用來標記是否進行下一次迴圈,初始時設為1進入第一次迴圈,然後進入後初始化為 flag = 0,如果可以判斷為當前序列已經與中間序列 b[] 相等,那麼就不需要設 flag = 1,即不再進行下一次迴圈。本迴圈再排序迭代一次即結束。


for(i = 0; i < n / k; i++)
	sort(a + i * k, a + (i + 1) * k);
sort(a + n / k * k, a + n);

這程式碼裡面出現兩次 n / k ,而因為 n 和 k 都是整數所以 n / k 的結果會向下取正。比如 n = 10,k = 3時,n / k = 3。

如果當最後一個組非 k 倍數時,比如上面的情況,那麼 for 迴圈會對前面整的組進行歸併和排序,而留下最後一個組單獨 sort 排序。

而單獨 sort 排序的話同樣有 n / k 並且還 * k,但同樣因為整型除法的向下取正,所以這裡的結果就是最後的組的首元素位置 n / k * k = 9。

當最後一個組為 k 倍數時,比如 n = 9, k = 3。那麼 for 迴圈剛好把三個組排序,而單獨的 sort 因為 n / k * k = 9, n = 9,所以只是對單一元素處理,不會導致其他的結果。

參考程式碼

參考理解

#include <bits/stdc++.h>
using namespace std;

int main() {
	int n, a[100], b[100], i, j;
	cin >> n;
	for(i = 0; i < n; i++)
		cin >> a[i];
	for(i = 0; i < n; i++)
		cin >> b[i];
	// 判斷是否是插入排序 
	for(i = 0; i < n && b[i] <= b[i+1]; i++);
	for(j = i + 1; j < n && a[j] == b[j]; j++);
	if(j == n){
		cout << "Insertion Sort" << endl;
		sort(a, a + i + 2); 
	}
	else{
		cout << "Merge Sort" << endl;
		int k = 1, flag = 1;
		while(flag){
			flag = 0;
			for(i = 0; i < n; i++)
				if(a[i] != b[i])
					flag = 1;
			k *= 2;
			for(i = 0; i < n / k; i++)
				sort(a + i * k, a + (i + 1) * k);
			sort(a + n / k * k, a + n);
		}
	}
	for(i = 0; i < n; i++)
		cout << (i ? " " : "") << a[i];
}