归并排序笔记

归并排序的步骤

归并排序是一种分治的方法,其步骤为以下几步:

  1. 确定分界点mid;
  2. 递归左右矩阵
  3. 将左右矩阵归一

归并与快排的区别:顺序不同。快排是先合并后递归(也可以理解为同时),归并是先递归后合并。

合并的操作

数组1已经排序:[1,3,4,6,6,8],指针 i
数组2已排序:[2,4,5,7,8,9],指针 j
归并流程图

归并排序的时间复杂度

为O(nlogn),与快速排序相同。
归并排序的优势:排序稳定——两数相同,位置不变。

归并排序的模板

#include <iostream>
const int N=100000;
void merge_sort(int q[N],int l,int r){
    if(l>=r) return;
    int mid=(l+r)>>1;/*步骤1 确定分界点*/
    int tem[N];
    int i=l,j=mid+1,k=0;
    merge_sort(q,l,mid),merge_sort(q,mid+1,r);/*步骤2,递归*/
    while(i<=mid&&j<=r){/*步骤3,归并*/
        if(q[i]<q[j]) tem[k++]=q[i++];
        else tem[k++]=q[j++];
    }
    while(i<=mid) tem[k++]=q[i++];
    while(j<=r) tem[k++]=q[j++];
    for(i=l,k=0;i<=r;i++,k++) q[i]=tem[k];
}
int main(){
    int n;
    int i;
    int q[N];
    scanf("%d",&n);
    for(i=0;i<n;i++) scanf("%d",&q[i]);
    merge_sort(q,0,n-1);
    for(i=0;i<n;i++) printf("%d ",q[i]);
}

逆序对的个数

逆序对的定义

数组中任选前后两个数,前面数>后面数的数对。
[图片待插入]

求逆序对个数的步骤

求逆序对个数的思想是正统的分治思想。我们首先还是要确定数组分界点,对于逆序对存在的情况,我们可以有以下分类:

  1. 两个数同时在左
  2. 两个数同时在右
  3. 两个数一左一右
    [图片待插入]
    当pi>pj时,后面的所有数都比pj大,对应的逆序对个数就有mid-i+1个。
#include <iostream>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int q[N];
int n;
LL merge_sort(int l,int r){
    if(l>=r) return 0;
    int mid=(l+r)>>1;/*确定分界点*/
    LL res=merge_sort(l,mid)+merge_sort(mid+1,r);/*计算两侧的逆序对*/
    int tem[N];
    int k=0,j=mid+1,i=l;
    while(i<=mid && j<=r){
        if(q[i]>q[j]){
            tem[k++]=q[j++];
            res+=mid-i+1;/*计算跨跃型逆序对*/
        }
        else tem[k++]=q[i++];
    }
    /*扫尾*/
    while(i<=mid) tem[k++]=q[i++];/*没有继续加res*/
    while(j<=r) tem[k++]=q[j++];
    for(i=l,j=0;i<=r;i++,j++) q[i]=tem[j];
    return res;
}
int main(){
    int i;
    cin>>n;
    for(i=0;i<n;i++) cin>>q[i];
    cout<<merge_sort(0,n-1)<<endl;
    return 0;
}

还需要补充的知识点:

  1. 指针的用法;
  2. const的用法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值