PAT-ADVANCED1098——Insertion or Heap Sort
題目描述:
題目翻譯:
1098 插入排序與堆排序
根據維基百科的定義如下:
插入排序迭代,每次重複消耗一個輸入元素,並生成排序的輸出列表。 每次迭代,插入排序都會從輸入資料中刪除一個元素,在排序列表中找到它所屬的位置,然後將其插入到那裡。 它重複直到沒有輸入元素。
堆排序將其輸入劃分為排序和未排序區域,並通過提取最大元素並將其移動到排序區域來迭代縮小未排序區域。 它涉及使用堆資料結構而不是線性時間搜尋來找到最大值。
現在給出初始的整數序列,以及一些序列,這是一些排序方法的幾次迭代的結果,你能告訴我們正在使用哪種排序方法嗎?
輸入格式:
每個輸入檔案包含一個測試用例。在每個測試用例中,第一行給出一個正整數N(<= 100)。接下來的一行給出N個整數,作為初始序列。最後一行給出N個整數,代表某排序演算法的中間序列。假設目標序列是升序。 一行中的所有數字都由一個空格分隔。
輸出格式:
對每個測試用例,在第一行輸出“Insertion Sort”或“Heap Sort”來說明產生該中間序列所使用的排序演算法。然後再執行此演算法一次迭代,並在第二行輸出結果序列。 保證每個測試用例的答案都是唯一的。 一行中的所有數字必須用空格分隔,並且行尾必須沒有多餘的空格。
輸入樣例1:
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
輸出樣例1:
Insertion Sort
1 2 3 5 7 8 9 4 6 0
輸入樣例2:
10
3 1 2 8 7 5 9 4 6 0
6 4 5 1 0 3 2 7 8 9
輸出樣例2:
Heap Sort 5 4 3 1 0 2 6 7 8 9
知識點:插入排序、堆排序
思路:先判斷是否是插入排序,再分別進行下一步操作
(1)如果是插入排序,尋找到已經排好序的前k - 1個元素,對第k個元素進行插入排序。
(2)如果是堆排序,尋找到位置k,使得k + 1之後的元素已經排好序。對[0, k]範圍內的元素,先交換0和k位置的值,再對[0, k - 1]範圍內的堆頂元素,即0位置的元素進下沉操作。
如果是插入排序,時間複雜度是O(N)。而如果是堆排序,由於我們需要一個雙重迴圈來尋找位置k,因此時間複雜度是O(N ^ 2)。空間複雜度均是O(1)。
C++程式碼:
#include<iostream> #include<vector> #include<algorithm> using namespace std; int N; vector<int> input1; vector<int> input2; bool isInsertionSort(); void nextInsertionSort(); void nextHeapSort(); void print(); int main() { cin >> N; int num; for(int i = 0; i < N; i++) { cin >> num; input1.push_back(num); } for(int i = 0; i < N; i++) { cin >> num; input2.push_back(num); } if(isInsertionSort()) { cout << "Insertion Sort" << endl; nextInsertionSort(); } else { cout << "Heap Sort" << endl; nextHeapSort(); } print(); return 0; } bool isInsertionSort() { int k = 0; for(int i = 0; i < N - 1; i++) { if(input2[i] > input2[i + 1]) { k = i + 1; break; } } for(int i = k; i < N; i++) { if(input1[i] != input2[i]) { return false; } } return true; } void nextInsertionSort() { int k = 0; for(int i = 0; i < N - 1; i++) { if(input2[i] > input2[i + 1]) { k = i + 1; break; } } int j = k - 1; int temp = input2[k]; for(; input2[j] > temp; j--) { input2[j + 1] = input2[j]; } input2[j + 1] = temp; } void nextHeapSort() { int k; for(int i = N - 1; i >= 0; i--) { bool flag = true; for(int j = 0; j < i; j++) { if(input2[j] > input2[i]) { flag = false; } } if(!flag) { k = i; break; } } swap(input2[0], input2[k]); int i = 0; int j = 2 * i + 1; while(j <= k - 1) { if(j + 1 <= k - 1 && input2[j + 1] > input2[j]) { j = j + 1; } if(input2[j] > input2[i]) { swap(input2[i], input2[j]); i = j; j = 2 * i + 1; }else{ break; } } } void print() { for(int i = 0; i < input2.size(); i++) { cout << input2[i]; if(i != input2.size() - 1) { cout << " "; } } cout << endl; }
C++解題報告: