1035 插入与归并

第一种方法。

直接模拟插入排序和非递归的归并排序。。。

#include<iostream>
#include<algorithm>
using namespace std;

int n;
int a[111] = {0},b[111]= {0},temp[111] = {0};
bool flag = false;//表示是否和中间序列相同
bool isSame() {//判断当前序列与中间序列是否相同
    for(int i =1; i <= n; ++i)
        if(a[i] != b[i]) return false;
    return true;
}
void print(int t) {//打印结果
    if(t == 0) printf("Insertion Sort\n");
    else if(t == 1)printf("Merge Sort\n");
    else ;
    for(int i = 1; i <= n; ++i) {
        cout<<a[i];
        if(i < n) printf(" ");
    }
    printf("\n");
}
void insertSort() {//插入排序,升序
    for(int i = 2; i <= n; ++i) {
        if(a[i] < a[i-1] ) { //当前的元素小于前面的元素 
            int j = i;
            a[0] = a[i];//设置哨兵
            while(a[j-1] > a[0]) {
                a[j] = a[j-1];
                --j;
            }
            a[j] = a[0];
        }
        if(isSame() && flag == false) {
            flag = true;
            continue;
        }
        if(flag == true) {
            print(0);
            return ;
        }
    }
}
void mergeSort() {//非递归的归并排序,可以求出每一趟排序结束后的序列
    for(int step = 2; step/2 <= n; step*=2) { //每step个元素为一组
        for(int i = 1; i <= n; i+=step)//下标从1开始,对每组step升序排序
            sort(a+i,a+min(i+step,n+1));
        if(isSame() && flag == false) {
            flag = true;
            continue;
        }
        if(flag == true) {
            print(1);
            return ;
        }
    }
}
int main() {
    cin>>n;
    for(int i = 1; i <= n; ++i) { //输入原始序列
        cin>>a[i];
        temp[i] = a[i];
    }
    for(int i = 1; i <= n; ++i)//输入中间序列
        cin>>b[i];
    insertSort();//插入排序 
    if(flag == false) {
        for(int i = 1; i <= n; ++i) //恢复原始序列
            a[i] = temp[i];
        mergeSort();//非递归的归并排序
    }
    return 0;
}

 

 第二种方法。

一,对于插入排序。

原始序列:3 1 2 8 7 5 9 4 6 0

中间序列:1 2 3 7 8 5 9 4 6 0

发现标红的序列已经有序,并且中间序列与原始序列的未标红部分全部相同,说明这是插入排序。

原始序列:3 1 2 8 7 5 9 4 0 6
中间序列:1 3 2 8 5 7 4 9 0 6

发现标红的序列已经有序,并且中间序列与原始序列的未标红部分不完全相同,说明这不是插入排序。

二,非递归的归并排序和第一种方法的一样。

注意点:

一,原始序列可能存在多个相同的元素,所以第12行代码的判断条件,必须写成b[i] <= b[i+1], 否则测试点4无法通过 。

#include<iostream>
#include<algorithm>
using namespace std;

int main() {
    int n,a[111]= {0},b[111]= {0},i,j;
    cin>>n;
    for(i = 1; i <= n; ++i)//输入原始序列
        cin>>a[i];
    for(i = 1; i <= n; ++i)//输入中间序列
        cin>>b[i];
    for(i = 1; i < n && b[i] <= b[i+1]; ++i); //找到中间序列的有序区的最后一个元素的下标
    for(j = i+1; j <= n && b[j] == a[j]; ++j);//从中间序列的无序区的第一个元素下标j开始,与同一下标开始的原始序列的元素逐一比较
    if(j > n) {//比较结束,且每个元素都相同,说明时是插入排序
        printf("Insertion Sort\n");
        sort(b+1,b+min(i+2,n+1));//再迭代一轮
        for(i = 1; i <= n; ++i) {
            if(i > 1) printf(" ");
            cout<<b[i];
        }
    } else {
        printf("Merge Sort\n");
        for(int step = 2; step/2 <= n; step *= 2) {
            for(i = 1; i <= n; i+=step)
                sort(a+i,a+min(i+step,n+1)); //必须这么写 
            for(i = 1; i <= n; ++i)
                if(a[i] != b[i]) break;
            if(i > n) { //再迭代一轮
                step *= 2;
                for(i = 1; i <= n; i+=step)
                    sort(a+i,a+min(i+step,n+1));
                for(int i = 1; i <= n; ++i) {
                    if(i > 1) printf(" ");
                    cout<<a[i];
                }
                return 0;
            }
        }
    }
    return 0;
}

 

 

 

posted @ 2020-02-18 16:43  tangq123  阅读(324)  评论(0编辑  收藏  举报