09-排序2 Insert or Merge (25分)

在头文件 algorithm 中,还有像merge这样的函数。

算法的选择是多种多样的,选择自己熟悉的。


唠叨两句。写这个代码的时候,一开始我也有考虑不周全的地方,也曾到网上搜索别人的代码示例。

遗憾的是有些博客写的代码也是有疏漏,有些测试并不能通过。

每个人都有自己的代码风格,看别人的代码并不会像看自己的代码一样顺畅。贴出错误的代码除了误导别人的恶作剧之外,毫无意义。

我相信,代码写错了的博主并不是有心的,也许只是贴错了版本。

我有在下面指出,希望他们看到的时候,能够修改一下。


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

bool isMergeSort(int *init, int *arr, int n);
int getMergeLength(int *arr, int n);
void mergeSortOnce(int *arr, int n, int len);

int main(void) {
    int n;
    cin >> n;
    int *init = new int[n];
    int *arr = new int[n];
    for(int i = 0; i < n; ++i)
        cin >> init[i];
    for(int i = 0; i < n; ++i)
        cin >> arr[i];

    if(isMergeSort(init, arr, n)) {
        cout << "Merge Sort" << endl;
        mergeSortOnce(arr, n, getMergeLength(arr, n));
    } else
        cout << "Insertion Sort" << endl;

    cout << arr[0];
    for(int i = 1; i < n; ++i)
        cout << " " << arr[i];

    delete[] init;
    delete[] arr;
    return 0;
}

/*
 * 1. 从前面找第一个反序的元素索引 -> 有序子列元素个数。
 * 2. 判断从该索引开始,是否与原始数列一致。若一致,是插入排序,否则是归并排序。
*/
bool isMergeSort(int *init, int *arr, int n) {
    int len = 1;    //记录插入排序中,有序子列的个数。
    for(int i = 0; i < n - 1; ++i) {
        if(arr[i] > arr[i + 1]) {
            len = i + 1;
            break;
        }
    }

    for(int i = len; i < n; ++i)
        if(arr[i] != init[i]) return true;

    sort(arr, arr + len + 1);   //若是插入排序,直接在这里完成下一趟插入。
    return false;
}

int getMergeLength(int *arr, int n) {
    for(int len = 2; len <= n/2; len *= 2) {    //记录归并段的长度,从2开始。
//        for(int i = len; i < n; i += 2*len) {   //判断相邻归并段是否是一个更大的归并段。
//            if(arr[i - 1] > arr[i]) return len; //上一个归并段的最后一个元素和下一个归并段的第一个元素比较。
//        }
        //lazy way.
        int i;
        for(i = 0; i <= n - 2*len; i += 2*len)
            if(!is_sorted(arr + i, arr + i + 2 *len)) return len;
        if(!is_sorted(arr + i, arr + n)) return len;
    }

    return n;  //全部元素有序,输入数据有误。
}

void mergeSortOnce(int *arr, int n, int len) {
    int i = 0;
    for(; i < n - 2*len; i += 2*len) {
        sort(arr + i, arr + i + 2*len);
    }
    sort(arr + i, arr + n);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值