归并排序

归并排序基础代码

#include
using namespace std;
#define N 100005
int A[N],n,temp[N];
void MergeSort(int l,int h){
     
     if(l>=h) return;
     int mid=(l+h)/2;
     MergeSort(l,mid);
     MergeSort(mid+1,h);
     int i=l,j=mid+1,k=0;
     while(i<=mid&&j<=h)
     {
     
         if(A[i]<=A[j])
            temp[k++]=A[i++];
         else temp[k++]=A[j++];
     }
     while(i<=mid) temp[k++]=A[i++];
     while(j<=h) temp[k++]=A[j++];
     for(int i=l,j=0;i<=h;i++,j++)
        A[i]=temp[j];
}
int main(){
     
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&A[i]);
    MergeSort(0,n-1);
    for(int j=0;j<n;j++)
        printf("%d ",A[j]);
    return 0;
}
/*
6
2 1 3 6 5 8
*/

与快排不同,归并排序要先划分区间再自底向上排序
即现递归再实现排序功能

归并排序应用

逆序数

#include
using namespace std;
#define N 100005
int A[N],n,temp[N];
long long sum;
void MergeSort(int l,int h){
     
     if(l>=h) return;
     int mid=(l+h)/2;
     MergeSort(l,mid);
     MergeSort(mid+1,h);
     int i=l,j=mid+1,k=0;
     while(i<=mid&&j<=h)
     {
     
         if(A[i]<=A[j])
            temp[k++]=A[i++];
         else{
     
                temp[k++]=A[j++];
                sum+=mid-i+1;
                printf("%d\n",sum);
         }
     }
     while(i<=mid) temp[k++]=A[i++];
     while(j<=h) temp[k++]=A[j++];
     for(int i=l,j=0;i<=h;i++,j++)
     {
     
         A[i]=temp[j];
         printf("%d  ",A[i]);
     }
     printf("**************\n");

}
int main(){
     
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&A[i]);
    MergeSort(0,n-1);

    printf("%lld",sum);
    return 0;
}
/*
6
2 1 3 6 5 8
*/

运行结果及过程
归并排序_第1张图片
逆序数编写过程中,int sum发生溢出,将其改为long long sum成功解决问题。
观察逆序队代码,只需在归并基础代码上添加一行 s u m + = m i d − i + 1 ; sum+=mid-i+1; sum+=midi+1;
在归并的过程中sum来源于三部分:

  • L到mid的内部逆序数
  • mid+1到h的内部逆序数
  • L到mid块对于mid+1到h的逆序数
    为成功完成逆序队干杯
    归并排序_第2张图片

你可能感兴趣的:(C++数据结构,c++)