归并排序 -- 稳定(c++)

先来看这样一个问题,现在你有两个有序数组a和b,如何把他们合并为一个新的有序数组c?

方法很简单,用两个变量p1和p2分别表示两个数组未被取出的元素中最小元素的下标,初始为 0。然后每次取出a[p1]和b[p2]中较小的那个放进新的数组里。如果取出的是a[p1],那p1就自增 1;反之,p2就自增 1。

如果有数组被取空了,那就把另一个数组剩下的都放进来就可以了。

参考代码如下:

int n = 5, m = 5;  // 两个数组的大小
int a[5] = {1, 3, 5, 7, 9};
int b[5] = {2, 4, 6, 8, 10};
int c[10];
int p1 = 0, p2 = 0, p = 0;
while (p1 < n && p2 < m) {
    if (a[p1] <= b[p2]) {
        c[p] = a[p1];
        p1++;
    } else {
        c[p] = b[p2];
        p2++;
    }
    p++;
}
while (p1 < n) {
    c[p] = a[p1];
    p++;
    p1++;
}
while (p2 < m) {
    c[p] = b[p2];
    p++;
    p2++;
}

归并排序的基本思想是分治,每次把待排序的区间分成两半,递归地处理。等到左右两部分都是有序后,再进行归并操作让整个数组有序。

参考代码如下:

int a[100005], b[100005];
void merge(int l, int r) {
    int p1 = l, mid = (l + r) / 2, p2 = mid + 1, p = l;
    while (p1 <= mid && p2 <= r) {
        if (a[p1] <= a[p2]) {
            b[p] = a[p1];
            p1++;
        } else {
            b[p] = a[p2];
            p2++;
        }
        p++;
    }
    while (p1 <= mid) {
        b[p] = a[p1];
        p++;
        p1++;
    }
    while (p2 <= r) {
        b[p] = a[p2];
        p++;
        p2++;
    }
    for (int i = l; i <= r; i++) {
        a[i] = b[i];
    }
}
void merge_sort(int l, int r) {
    if (l == r) {
        return;
    }
    int mid = (l + r) / 2;
    merge_sort(l, mid);
    merge_sort(mid + 1, r);
    merge(l, r);
}

上面的merge_sort函数每次对 [l,r] 区间的元素进行归并排序。如果当前区间只有一个元素,就说明已经排序好了,直接返回。否则,把区间划分为 [l,mid] 和 [mid+1,r] 两部分递归处理,其mid=⌊2l+r​⌋。

执行归并操作时,先把两个有序的区间合并到一个新数组b中,最后再复制回原数组里

完整代码

#include <iostream>
using namespace std;
int a[100005], b[100005];
void merge(int l, int r) {
    int p1 = l, mid = (l + r) / 2, p2 = mid + 1, p = l;
    while (p1 <= mid && p2 <= r) {
        if (a[p1] <= a[p2]) {
            b[p] = a[p1];
            p1++;
        } else {
            b[p] = a[p2];
            p2++;
        }
        p++;
    }
    while (p1 <= mid) {
        b[p] = a[p1];
        p++;
        p1++;
    }
    while (p2 <= r) {
        b[p] = a[p2];
        p++;
        p2++;
    }
    for(int i = l; i <= r; i++){
        a[i] = b[i];
    }
}
void merge_sort(int l, int r) {
    if (l == r){
        return ;
    }
   int mid=(l+r) / 2;
   merge_sort(l,mid);
   merge_sort(mid + 1,r);
   merge(l,r);
}
int main() {
    int n;
    
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    merge_sort(0, n - 1);
    for (int i = 0; i < n; i++) {
        cout << a[i] << " ";
    }
    return 0;
}

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值