PAT : 1035. 插入与归并(25)
2015-03-31 18:27
330 查看
根据维基百科的定义:
插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。
归并排序进行如下迭代操作:首先将原始序列看成N个只包含1个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下1个有序的序列。
现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?
输入格式:
输入在第一行给出正整数N (<=100);随后一行给出原始序列的N个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。
输出格式:
首先在第1行中输出“Insertion Sort”表示插入排序、或“Merge Sort”表示归并排序;然后在第2行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行末不得有多余空格。
输入样例1:
输出样例1:
输入样例2:
输出样例2:
插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。
归并排序进行如下迭代操作:首先将原始序列看成N个只包含1个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下1个有序的序列。
现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?
输入格式:
输入在第一行给出正整数N (<=100);随后一行给出原始序列的N个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。
输出格式:
首先在第1行中输出“Insertion Sort”表示插入排序、或“Merge Sort”表示归并排序;然后在第2行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行末不得有多余空格。
输入样例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 0 6 1 3 2 8 5 7 4 9 0 6
输出样例2:
Merge Sort 1 2 3 8 4 5 7 9 0 6
很多人都用的是实现两个算法,之后去比对的方法,我不打算这么做,我想应该能够识别这两种算法产生的序列的特征,简单来说,插入排序就是前一段有序,后一段不一定有序,归并排序就是一段一段的数各自有序,但是在识别归并排序的时候没想到一个点让我吃了大亏。因为段与段之间可能也是有序的,就是说比如段长为2,但也许某相邻的若干个段连起来也是有序的,这样递增的段长就成了4或者更大,这给识别就造成了难度,我原以为只要求出每个递增段的段长,如果每个段的长度都相等(排除最后一段,因为最后一段可能不足一段的段长)就是归并,现在想来真是图样图森破。好在http://blog.csdn.net/fang_abc/article/details/44113969给我了启发,非常感谢。他的思想就是拿到第一段递增段的长度,将这个长度作为步长,将数列分为k个段,看这每个段是否全部有序,如果不是,段长除以2重复以上过程。这里我觉得原帖有一个漏洞,如果第一个递增段长为6,即由3个段长为2的段拼接成,每次除2会出问题,于是我在最前面加了一个判断,判断第一个递增段长是否是2的指数,如果是,继续,如果不是,直接设置段长为2
关于判断是否为2的指数的函数func(),原理是i(设i为2的指数)与i-1的二进制按位与的结果是0,如8的二进制数为1000,7为0111,按位与的结果即为0
#include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; bool issorted (int *numList, int length) { for(int i = 1; i < length; i++) { if(numList[i] < numList[i-1]) return false; } return true; } int func(int i) { return ((i > 0) && ((i & (i - 1)) == 0)); } int main() { int flag = 0, seqlength = 1; int n; scanf("%d", &n); int *numList = (int *) malloc (n * sizeof(int)); int *ul = (int *) malloc (n * sizeof(int)); int i; for(i = 0; i < n; i++) scanf("%d", &ul[i]); for(i = 0; i < n; i++) { scanf("%d", &numList[i]); if(i >= 1) { if(numList[i] >= numList[i-1] && flag == 0) seqlength++; else flag = 1; } } int sortlength = seqlength; sort(ul, ul+seqlength); for(i = 0; i < n; i++) if(ul[i] != numList[i]) break; if(i == n) flag = 1; else { flag = 0; int allpass = 0; if(! func(sortlength)) sortlength = 2; else { while(sortlength >= 2 && allpass == 0) { allpass = 1; int k = n / sortlength; for(i = 0; i < k; i++) if(! issorted(numList+i*sortlength, sortlength)) { allpass = 0; break; } if(! issorted(numList+k*sortlength, n-k*sortlength)) allpass = 0; if(allpass == 0) sortlength /= 2; } } } if(flag == 0) { printf("Merge Sort\n"); int step = sortlength*2; if(step >= n) sort(numList, numList+n); else { int k = n/step; for(i = 0; i < k; i++) sort(numList+i*step, numList+(i+1)*step); if(n % step != 0) sort(numList+k*step, numList+n); } } else { printf("Insertion Sort\n"); sort(numList, numList+seqlength+1); } for(i = 0; i < n; i++) { printf("%d", numList[i]); if(i < n - 1) printf(" "); } printf("\n"); return 0; }
相关文章推荐
- pat 乙级 1035. 插入与归并(25)
- PAT乙级 1035. 插入与归并(25)
- PAT乙级 1035. 插入与归并(25)
- PAT乙级 1035. 插入与归并(25)--模拟插入归并算法
- PAT Basic 1035. 插入与归并(25)(C语言实现)
- PAT乙级1035. 插入与归并(25)
- C++ - PAT - 1035. 插入与归并(25)
- 1035. 插入与归并(25)-浙大PAT乙级真题
- 1035. 插入与归并(25) PAT
- PAT乙级—1035. 插入与归并(25)-native
- PAT-乙级-1035. 插入与归并(25)
- PAT 1035. 插入与归并(25)
- PAT 1035. 插入与归并(25)
- 1035. 插入与归并(25)-浙大PAT乙级真题java实现
- PAT乙级-1035 插入与归并(25)
- PAT乙级别.1035. 插入与归并(25)
- PAT-B 1035. 插入与归并(25)
- 【PAT】1035. 插入与归并(25)
- PAT (Basic Level) Practise (中文) 1035. 插入与归并(25)
- PAT (Basic Level) Practise (中文)1035. 插入与归并(25)