中国大学MOOC-数据结构基础习题集、07-2、Insert or Merge

题目链接:http://www.patest.cn/contests/mooc-ds/07-2

题目分析:这是一道考察插入排序和归并排序的一道题。题目可能有点难以理解,这里稍加解释一下:

  首先,输入的第一行是一个整型数,代表数据的个数。第二行是起始数据,排序从这里开始。第三行是目标(或者叫终止)数据,排序到这里结束。我们知道插入排序和合并排序是有很大不同的,如果是目标数据(我们暂且这么叫)是由插入排序生成的,就输出Insertion Sort;如果是目标数据是由归并排序生成的,就输出Merge Sort。不管是何种输入,都要输出这种排序的“下一步”。注意这里的“下一步”是“一大步”,也就是“一趟”归并排序。

特别说明:

  1. 首先推荐一个函数:inplace_merge函数。它的作用和merge函数差不多,只不过是在一个容器中进行归并。

  函数参数:inplace_merge(first,mid,last,compare); // 将[first,mid) 和 [mid,last)这两个区间进行归并成一个有序序列。

  有了这个可以不用自己写merge了。但是此处博主并没有用到它。这里只是教大家用C++的STL解决实际问题。使用使需要引头文件#include <algorithm>。

  如果相对merge类函数有更多了解,不妨阅读:http://www.cppblog.com/zhangyq/archive/2012/02/05/164060.html

  2. 刚才说到博主这里没有用到merge类的函数,是因为博主压根没有用“归并排序”。当时博主的最直接的想法就是用sort替代真实的MSort和Merge。所以算是偷懒吧。另外程序中有点了乱,有的地方

  3. 插入/合并排序可能出现一趟下来没有改变的情况,要输出有改变的才可以。也就是说你的输出不能和输入的第三行的那串数字相同。这点略坑。可以按照下面的方法测试下自己的代码。

建议测试用例:

  测试用例一(这个没什么好说的,肯定都能过,为了与用例二比照):

测试输入:
10
3 1 2 4 5 6 7 9 8 10
1 3 2 4 5 6 7 9 8 10
 
预期结果:
Insertion Sort
1 2 3 4 5 6 7 9 8 10  

  测试用例二(重点):

测试输入:
10
3 1 2 4 5 6 7 9 8 10
1 2 3 4 5 6 7 9 8 10
预期结果:
Insertion Sort
1 2 3 4 5 6 7 8 9 10
而不是:
Insertion Sort
1 2 3 4 5 6 7 9 8 10
(和输入第三行一样了,是错的)

代码分析:

  每个函数前面都有注释,相信大家都能看得懂。

  就像前面说的一样,博主只是用到了归并排序的思想,没有真正实现归并排序。想看归并排序的同学,可以看作业07-1,我刚刚更新了归并排序。这里我是借助了sort函数简化代码。这样做有点偷懒,但是却十分方便。

  顺便解释一下,为什么在主函数中有a和aa两个数组。这是因为在判断IsInsert中,已经把a数组改变了,所以需要一个备份。就是这样,喵~

  1 #include <iostream>
  2 #include <algorithm>
  3 
  4 #define NOTEXIST -1
  5 
  6 using namespace std;
  7 
  8 // 判断两个数组是否相等
  9 bool isEqual(int a[], int b[], int n)
 10 {
 11     for(int i=0; i<n; i++)
 12         if(a[i] != b[i])
 13             return false;
 14     return true;
 15 }
 16 
 17 // 进行插入排序的移动元素操作
 18 int moveElement(int i, int a[])
 19 {
 20     int tmp = a[i];
 21     int j;
 22     for(j=i; j>0 && a[j-1] > tmp; j--)
 23         a[j] = a[j-1];
 24     a[j] = tmp;
 25     return j;
 26 }
 27 
 28 // 判断是不是插入排序
 29 int isInsertSort(int a[], int b[], int n)
 30 {
 31     for(int i=0; i<n; i++)
 32     {
 33         moveElement(i, a);
 34         if(isEqual(a, b, n) == true)
 35             return i;
 36     }
 37     return NOTEXIST;
 38 }
 39 
 40 // 非递归算法
 41 bool MSort( int A[], int B[], int N )
 42 {
 43     int step = 1;
 44     bool myFlag = false;
 45     while(step < N)
 46     {
 47         step *= 2;
 48         for(int i=0; i<N; i=i+step)
 49         {
 50             int first = i;
 51             int last = first + step;
 52             if(last >= N)
 53                 last = N;
 54             sort(A+first, A+last);
 55         }
 56         if(myFlag == true)
 57         {
 58             // 如果已经成功,走完了归并排序之后直接返回即可!注意此if语句应该位于下一个if语句之前!!
 59             if(isEqual(A, B, N) == false)
 60                 return true;
 61         }
 62         if(isEqual(A, B, N) == true)
 63         {
 64             // 如果发现和目标数据相同,则置myFlag标识为true,代表已经成功,只需要再走一次归并排序即可!
 65             myFlag = true;
 66         }
 67     }
 68     return false;
 69 }
 70 
 71 // 输出数组内的元素
 72 void outputElement(int x[], int n)
 73 {
 74     for(int i=0; i<n; i++)
 75     {
 76         if(i != n-1)
 77             cout << x[i] << " ";
 78         else
 79             cout << x[i];
 80     }
 81     cout << endl;
 82 }
 83 
 84 int main()
 85 {
 86     int n;
 87     cin >> n;
 88     int *a = new int[n];
 89     int *aa = new int[n];
 90     for(int i=0; i<n; i++)
 91     {
 92         cin >> a[i];
 93         aa[i] = a[i];
 94     }
 95 
 96     int *b = new int[n];
 97     for(int j=0; j<n; j++)
 98         cin >> b[j];
 99     int IS = isInsertSort(a, b, n);
100     if(IS != NOTEXIST)
101     {
102         cout << "Insertion Sort" << endl;
103         while(isEqual(a, b, n) == true)
104         {
105             IS = moveElement(IS+1, a);
106         }
107         outputElement(a, n);
108     }
109     else
110     {
111         cout << "Merge Sort" << endl;
112         MSort(aa, b, n);
113         outputElement(aa, n);
114     }
115     return 0;
116 }

AC成果:

posted @ 2015-01-13 21:38  聪明的聪聪  阅读(439)  评论(2编辑  收藏  举报