首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >论分治与归并思想

论分治与归并思想

作者头像
_DIY
发布2019-09-11 17:28:28
4470
发布2019-09-11 17:28:28
举报

归并排序

要想了解归并思想,就离不开对归并排序的理解,从前看别人的代码百思不得其解,后来看到一张图片顿时领悟,附下:

每次比较两个数组,注意可以是一个数组的两个不同的区间,每次将较小的数存储在一个临时数组中,这样就完成了归并排序。当然,前提是这两个数组是有序的,那么,问题是,如何让这两个数组是有序的呢,这就用到了递归。

    merge_sort(left, mid);
    merge_sort(mid+1, right);

为什么要用递归来实现呢,看下一张图片。

例题

如果只是说理论就显得苦涩难懂,下面贴一个来自洛谷的题目,小试身手。 https://www.luogu.org/problem/P1908 详细讲解已经在代码注释中标明

#include<bits/stdc++.h>
using namespace std;
int N;
int a[100000+10], temp[100000+10];
long long ans = 0;          //ans用于记录逆序对的数量
void merge_sort(int l, int r)
{
    if(l == r) return ;
    int k = 0 ,mid = (l + r)/2;
    merge_sort(l, mid);             
    merge_sort(mid+1, r);
    //注意一定要先递归,这样就可以保证l ~ mid区间、mid + 1 ~ r区间已经完成了从小到大的排序
    int i = l, j = mid + 1;
    while(i <= mid && j <= r)
    {
        if(a[i] < a[j])
            temp[k++] = a[i++];       //将较小的数字存储在临时数组中
        else 
        {
            temp[k++] = a[j++];
            ans += mid - i + 1;     //因为a[i]-a[mid]按递增顺序排列 所以a[j]之前有mid-i+1对逆序对

        }
    }
    while(i <= mid)         //如果a[i...mid]有剩余
        temp[k++] = a[i++];     
    while(j <= r)           //如果a[j...r]有剩余
        temp[k++] = a[j++];
    for(k = 0; k <= (r - l); k++)
        a[l + k] = temp[k];         //这里就完成了两块区间的有序归并

}
int main()
{
    std::ios::sync_with_stdio(false);
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    cin >> N;
    memset(a, 0, sizeof(a));
    memset(temp, 0, sizeof(temp));
    for(int i = 0; i < N; i++)
        cin >> a[i];
    merge_sort(0, N-1);
    cout << ans << endl;
}

以上代码同样可以用于排序(采用了分治排序)

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-08-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 归并排序
  • 例题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档