您的位置:首页 > 理论基础 > 数据结构算法

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

2015-01-13 21:38 411 查看
题目链接: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

(和输入第三行一样了,是错的)

[b]代码分析:[/b]

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

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

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

#include <iostream>
#include <algorithm>

#define NOTEXIST -1

using namespace std;

// 判断两个数组是否相等
bool isEqual(int a[], int b[], int n)
{
for(int i=0; i<n; i++)
if(a[i] != b[i])
return false;
return true;
}

// 进行插入排序的移动元素操作
int moveElement(int i, int a[])
{
int tmp = a[i];
int j;
for(j=i; j>0 && a[j-1] > tmp; j--)
a[j] = a[j-1];
a[j] = tmp;
return j;
}

// 判断是不是插入排序
int isInsertSort(int a[], int b[], int n)
{
for(int i=0; i<n; i++)
{
moveElement(i, a);
if(isEqual(a, b, n) == true)
return i;
}
return NOTEXIST;
}

// 非递归算法
bool MSort( int A[], int B[], int N )
{
int step = 1;
bool myFlag = false;
while(step < N)
{
step *= 2;
for(int i=0; i<N; i=i+step)
{
int first = i;
int last = first + step;
if(last >= N)
last = N;
sort(A+first, A+last);
}
if(myFlag == true)
{
// 如果已经成功,走完了归并排序之后直接返回即可!注意此if语句应该位于下一个if语句之前!!
if(isEqual(A, B, N) == false)
return true;
}
if(isEqual(A, B, N) == true)
{
// 如果发现和目标数据相同,则置myFlag标识为true,代表已经成功,只需要再走一次归并排序即可!
myFlag = true;
}
}
return false;
}

// 输出数组内的元素
void outputElement(int x[], int n)
{
for(int i=0; i<n; i++)
{
if(i != n-1)
cout << x[i] << " ";
else
cout << x[i];
}
cout << endl;
}

int main()
{
int n;
cin >> n;
int *a = new int
;
int *aa = new int
;
for(int i=0; i<n; i++)
{
cin >> a[i];
aa[i] = a[i];
}

int *b = new int
;
for(int j=0; j<n; j++)
cin >> b[j];
int IS = isInsertSort(a, b, n);
if(IS != NOTEXIST)
{
cout << "Insertion Sort" << endl;
while(isEqual(a, b, n) == true)
{
IS = moveElement(IS+1, a);
}
outputElement(a, n);
}
else
{
cout << "Merge Sort" << endl;
MSort(aa, b, n);
outputElement(aa, n);
}
return 0;
}


AC成果:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: