轉跳點 :?
1035 插入與歸併 (25分)
根據維基百科的定義:
插入排序是迭代演算法,逐一獲得輸入資料,逐步產生有序的輸出序列。每步迭代中,演算法從輸入序列中取出一元素,將之插入有序序列中正確的位置。如此迭代直到全部元素有序。
歸併排序進行如下迭代操作:首先將原始序列看成 n 個只包含 1 個元素的有序子串行,然後每次迭代歸併兩個相鄰的有序子串行,直到最後只剩下 1 個有序的序列。
現給定原始序列和由某排序演算法產生的中間序列,請你判斷該演算法究竟是哪種排序演算法?
輸入在第一行給出正整數 n (≤100);隨後一行給出原始序列的 n 個整數;最後一行給出由某排序演算法產生的中間序列。這裡假設排序的目標序列是公升序。數字間以空格分隔。
首先在第 1 行中輸出insertion sort
表示插入排序、或merge sort
表示歸併排序;然後在第 2 行中輸出用該排序演算法再迭代一輪的結果序列。題目保證每組測試的結果是唯一的。數字間以空格分隔,且行首尾不得有多餘空格。
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
insertion sort
1 2 3 5 7 8 9 4 6 0
10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6
merge sort
1 2 3 8 4 5 7 9 0 6
這道題比較有意思,需要用到歸併排序和插入排序的知識,兩種排序的部落格我都寫了,自行轉跳。
這道題有兩種解法,
第一種是寫兩個排序演算法,每執行完一輪就比較一次,時間複雜度 t(o) = o(n^3+n^2logn),太暴力了
第二種是利用插入排序的特性:插入排序,前面是排好序的,後面是與初始序列相同。只要符合這個條件的就是插入,不符合就是歸併
用第一種方法暴力就行,但是第二種就需要對歸併和插入排序十分熟悉,因為要寫乙個單步的歸併和插入。插入的單步十分容易實現只要知道第幾個沒排好,繼承索引,找到位置插入就行了。而歸併就有些麻煩,需要完完整整的歸併。
ac**
1 #include 2 #include 3 #include 4
5 int merge = 0;
6 void insertsorted(int arr, int mid, int n);
7 void mergesorted(int arr, int mid, int n);
8 int arrayequal(int arr, int ary, int n);
9 void arrayprint(int arr, int n);
10 11 int main(void)
12 25
26 for (int i = 0; i < n; i++)
27
30
31 insertsorted(arr, mid, n);
32 if (merge)
33
36 37 return 0;
38 }
39 40 //插入排序
41 void insertsorted(int arr, int mid, int n)
42 54 arr[j] = temp;
55 56 if (arrayequal(arr, mid, n))
57
65 arr[j] = temp;
66 printf("insertion sort\n");
67 arrayprint(arr, n);
68 merge = 0;
69 return;
70 }
71 }
72 merge = 1;
73 }
74 75 void mergeadd(int arr, int left, int mid, int right, int *tmp)
76 84 while (i <= mid)
85
88 while (j <= right)
89
92 //把tmp中的內容拷給arr陣列中
93 //進行歸併的時候,處理的區間是arr[left,right),對應的會把
94 //這部分區間的陣列填到tmp[left,right)區間上
95 memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
96 }
97 98 void mergesort(int arr, int len, int *tmp, int mid, int n)
99 104 int flag = 0;
105
106 //定義乙個步長gap,初始值為1,相當於每次只合併兩個長度為1的元素
107 for (int gap = 1; gap <= len; gap *= 2)
108
117 int end = mid + gap;
118 if (end >= len)
119
122 mergeadd(arr, beg, mid, end, tmp);
123 }
124 if (flag)
125
130 if (arrayequal(arr, mid, n))
131
134 }
135 }
136 //歸併排序介面
137 void mergesorted(int arr, int mid, int n)
138
143 //輸出陣列
144 void arrayprint(int arr, int n)
145
150 }
151 //判斷相等
152 int arrayequal(int arr, int ary, int n)
153
160 }
161 return 1;
162 }
第二種:
1 #include 2 #include 3
4 int isinsertion(int n, int num, int mid);
5 int nextmerge(int n, int num, int mid);
6 int cmp(const void *a, const void *b)
7 8 int main()
9 17 for (i = 0; i < n; i++)
18
21 22 if (isinsertion(n, num, mid))
23
26 27 for (i = 0; i < n; i++)
28
31 return 0;
32 }
33 34 int isinsertion(int n, int num, int mid)
35 41 for (i++, lenth = i; i < n && mid[i] == num[i]; i++)
42
45 if (i < n)
46
49 printf("insertion sort\n");
50 lenth++;
51 qsort(num, lenth, sizeof(int), cmp);
52 return 0;
53 }
54 55 int nextmerge(int n, int num, int mid)
56 67 qsort(num + j * lenth, n % lenth, sizeof(int), cmp);
68 }
69 return 0;
70 }
偷懶了,用qsort」實現「歸併
pta不易,諸君共勉!
1035 插入與歸併
題目是pat乙級 思路 簡單修改插入排序和合併排序源 加入和目標比較若相等,就退出。注意 插入排序不是從第0個元素開始,是從第1個元素開始的。訓練目的 插入排序 合併排序 題目描述 根據維基百科的定義 插入排序是迭代演算法,逐一獲得輸入資料,逐步產生有序的輸出序列。每步迭代中,演算法從輸入序列中取出...
1035 插入與歸併
時間限制 200 ms 記憶體限制 65536 kb 長度限制 8000 b 判題程式 standard 作者 chen,yue 根據維基百科的定義 插入排序是迭代演算法,逐一獲得輸入資料,逐步產生有序的輸出序列。每步迭代中,演算法從輸入序列中取出一元素,將之插入有序序列中正確的位置。如此迭代直到全...
1035 插入與歸併
1035 插入與歸併 25 分 根據維基百科的定義 插入排序是迭代演算法,逐一獲得輸入資料,逐步產生有序的輸出序列。每步迭代中,演算法從輸入序列中取出一元素,將之插入有序序列中正確的位置。如此迭代直到全部元素有序。歸併排序進行如下迭代操作 首先將原始序列看成 n 個只包含 1 個元素的有序子串行,然...