转跳点 :

1035 插入与归并 (25分)
 

根据维基百科的定义:

插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。

归并排序进行如下迭代操作:首先将原始序列看成 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

  这道题比较有意思,需要用到归并排序和插入排序的知识,两种排序的博客我都写了,自行转跳。

这道题有两种解法,

    第一种是写两个排序算法,每执行完一轮就比较一次,时间复杂度 T(O) = O(N^3+N^2logN),太暴力了

    第二种是利用插入排序的特性:插入排序,前面是排好序的,后面是与初始序列相同。只要符合这个条件的就是插入,不符合就是归并

用第一种方法暴力就行,但是第二种就需要对归并和插入排序十分熟悉,因为要写一个单步的归并和插入。插入的单步十分容易实现只要知道第几个没排好,继承索引,找到位置插入就行了。而归并就有些麻烦,需要完完整整的归并。

AC代码

  1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
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 {
13 static int n;
14 int arr[101];
15 int ary[101];
16 int mid[101];
17
18 scanf("%d", &n);
19
20 for (int i = 0; i < n; i++)
21 {
22 scanf("%d", &arr[i]);
23 ary[i] = arr[i];
24 }
25
26 for (int i = 0; i < n; i++)
27 {
28 scanf("%d", &mid[i]);
29 }
30
31 InsertSorted(arr, mid, n);
32 if (Merge)
33 {
34 MergeSorted(ary, mid, n);
35 }
36
37 return 0;
38 }
39
40 //插入排序
41 void InsertSorted(int arr[], int mid[], int n)
42 {
43 int j, temp;
44
45 for (int i = 1; i < n; i++)
46 {
47 j = i;
48 temp = arr[i];
49 while (j > 0 && temp < arr[j - 1])
50 {
51 arr[j] = arr[j - 1];
52 j--;
53 }
54 arr[j] = temp;
55
56 if (ArrayEqual(arr, mid, n))
57 {
58 j = ++i;
59 temp = arr[i];
60 while (j > 0 && temp < arr[j - 1])
61 {
62 arr[j] = arr[j - 1];
63 j--;
64 }
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 {
77 int i = left;
78 int j = mid + 1;
79 int k = left;
80 while (i <= mid && j <= right)
81 {
82 tmp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
83 }
84 while (i <= mid)
85 {
86 tmp[k++] = arr[i++];
87 }
88 while (j <= right)
89 {
90 tmp[k++] = arr[j++];
91 }
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 {
100 if (len <= 1)
101 {
102 return;
103 }
104 int flag = 0;
105
106 //定义一个步长gap,初始值为1,相当于每次只合并两个长度为1的元素
107 for (int gap = 1; gap <= len; gap *= 2)
108 {
109 for (int i = 0; i <= len; i += 2 * gap)
110 {
111 int beg = i;
112 int mid = (gap - 1) + i;
113 if (mid >= len)
114 {
115 mid = len;
116 }
117 int end = mid + gap;
118 if (end >= len)
119 {
120 end = len;
121 }
122 MergeAdd(arr, beg, mid, end, tmp);
123 }
124 if (flag)
125 {
126 printf("Merge Sort\n");
127 ArrayPrint(arr, n);
128 return;
129 }
130 if (ArrayEqual(arr, mid, n))
131 {
132 flag = 1;
133 }
134 }
135 }
136 //归并排序接口
137 void MergeSorted(int arr[], int mid[], int n)
138 {
139 int *temp = malloc(sizeof(int) * n);
140 MergeSort(arr, n - 1, temp, mid, n);
141 free(temp);
142 }
143 //输出数组
144 void ArrayPrint(int arr[], int n)
145 {
146 for (int i = 0; i < n; i++)
147 {
148 printf("%d%s", arr[i], n - 1 == i ? "" : " ");
149 }
150 }
151 //判断相等
152 int ArrayEqual(int arr[], int ary[], int n)
153 {
154 for (int i = 0; i < n; i++)
155 {
156 if (arr[i] != ary[i])
157 {
158 return 0;
159 }
160 }
161 return 1;
162 }

第二种:

 1 #include <stdio.h>
2 #include <stdlib.h>
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) { return (*(int *)a) > (*(int *)b); }
7
8 int main()
9 {
10 int n, num[100], mid[100];
11 int i;
12 scanf("%d", &n);
13 for (i = 0; i < n; i++)
14 {
15 scanf("%d", &num[i]);
16 }
17 for (i = 0; i < n; i++)
18 {
19 scanf("%d", &mid[i]);
20 }
21
22 if (isinsertion(n, num, mid))
23 {
24 nextmerge(n, num, mid);
25 }
26
27 for (i = 0; i < n; i++)
28 {
29 printf("%d%s", num[i], i == n - 1 ? "" : " ");
30 }
31 return 0;
32 }
33
34 int isinsertion(int n, int num[], int mid[])
35 {
36 int i, lenth;
37 for (i = 0; i < n - 1 && mid[i] <= mid[i + 1]; i++)
38 {//前面是排好序的
39 continue;
40 }
41 for (i++, lenth = i; i < n && mid[i] == num[i]; i++)
42 {//后面是与初始序列相同
43 continue;
44 }
45 if (i < n)
46 {
47 return 1;
48 }
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 {
57 int i, j, lenth;
58 printf("Merge Sort\n");
59 for (lenth = 1, i = 0; i < n && lenth <= n; lenth *= 2)
60 { //只能一步步归并
61 for (i = 0; i < n && num[i] == mid[i]; i++)
62 ;
63 for (j = 0; j < n / lenth; j++)
64 {
65 qsort(num + j * lenth, lenth, sizeof(int), cmp);
66 }
67 qsort(num + j * lenth, n % lenth, sizeof(int), cmp);
68 }
69 return 0;
70 }

  偷懒了,用qsort”实现“归并

   PTA不易,诸君共勉!

P 1035 插入与归并的更多相关文章

  1. PAT-乙级-1035. 插入与归并(25)

    1035. 插入与归并(25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 根据维基百科的定义: 插入排序是迭 ...

  2. PAT 1035 插入与归并(25)(代码+思路+测试点分析)

    1035 插入与归并(25 分) 根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到 ...

  3. PAT (Basic Level) Practise (中文)-1035. 插入与归并(25)

    PAT (Basic Level) Practise (中文)-1035. 插入与归并(25)   http://www.patest.cn/contests/pat-b-practise/1035 ...

  4. PAT(B) 1035 插入与归并(Java)

    题目链接:1035 插入与归并 (25 point(s)) 参考博客:PAT乙级--1035(插入排序和归并)java实现熊仙森 题目描述 根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据, ...

  5. PAT——1035. 插入与归并

    根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序. 归并排序进行如下迭 ...

  6. PAT 1035. 插入与归并(25)

    根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序. 归并排序进行如下迭 ...

  7. PAT 1035 插入与归并

    https://pintia.cn/problem-sets/994805260223102976/problems/994805286714327040 据维基百科的定义: 插入排序是迭代算法,逐一 ...

  8. PAT 1035 插入与归并(25)

    原题:https://pintia.cn/problem-sets/994805260223102976/problems/994805286714327040传送门: 根据维基百科的定义: 插入排序 ...

  9. 1035 插入与归并 (25 分)C语言

    根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序. 归并排序进行如下迭 ...

随机推荐

  1. mysql 统计索引执行情况

    select distinct b.TABLE_SCHEMA,b.TABLE_NAME , b.INDEX_NAME , a.count_starfrom performance_schema.tab ...

  2. PostgreSQL存取jsonb

    从PostgreSQL 9.3开始,json就成了postgres里的一种数据类型,也就是和varchar.int一样,我们表里的一个字段的类型可以为json了. 与此同时,postgres还提供了j ...

  3. 获取Webshell方法总结

    一.CMS获取Webshell方法 搜索CMS网站程序名称 eg:phpcms拿webshell.wordpress后台拿webshell 二.非CMS获取Webshell方法 2.1数据库备份获取W ...

  4. 一道快速考察 Python 基础的面试题

    这是前一阵子群友发在群里的一道面试题,利用 Python 字典的特性,可以巧妙地使用精简代码达成完美解. 题目 将 data 转换成 new_data 这种形式,写出转换过程. data = { 'a ...

  5. 设计模式课程 设计模式精讲 18-2 迭代器模式coding

    1 代码演练 1.1 代码演练1(迭代器模式演练) 1.2 代码使用场景 1 代码演练 1.1 代码演练1(迭代器模式演练) 需求: 课程管理:需要实现课程可进行增添,删除,并能够打印出课程列表. u ...

  6. 设计模式课程 设计模式精讲 16-4 代理模式Coding-动态代理

    1 代码演练 1.1 动态代理 2 疑难解答 2.1 动态代理invoke怎么执行的? 2.2 感觉这块理解的不是很好,下边有时间再看看 1 代码演练 1.1 动态代理 重点: 重点关注动态代理类 测 ...

  7. Swift-关于Swift编程语言

    一.首先让我们看看苹果公司是怎么描述自己的Swift的: Swift 是编写程序的绝佳选择,无论是手机.电脑还是服务器,任何能跑代码的设备都是如此.它是一门集现代语言之大成,集结了苹果的工程师文化精髓 ...

  8. Jenkins安装 maven插件

    Maven Artifact ChoiceListProvider (Nexus)Maven Metadata Plugin for Jenkins CI serverMaven Release Pl ...

  9. MySQL 常用SQL 汇总

    1.查看当前应用连接,连接数突增排查 select user,SUBSTRING_INDEX(host,':',1) as ip , count(*) as count,db from informa ...

  10. Java垃圾回收机制详解和调优

    gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存.java语言并不要求jvm有gc,也没有规定gc如何工作.不过常用的jvm都有gc,而且大多数gc都使用类似的算法管理内存和执行收集 ...