排序算法——归并排序(ACWing)

算法原理

分治

算法步骤

  1. 确定分界点为中间位置,mid=(l+r)/2
  2. 递归排序左右两边
  3. 归并两个排好序的数组,合二为一(最难的部分),时间复杂度是O(n)
    双指针算法
    两个指针分别指向两个数组的开头,比较两个指针对应数值大小,小的放进新数组,该指针后移,直到一个指针到达数组末尾,将另外一个数组剩下的部分添加到新数组中。
    1 3 5 7 9
    2 4 5 8 10
    i=0,j=0;p[i]=p[0]=1<q[j]=q[1]=2,s[0]=p[0]=1;i++;i=1,j=0;
    i=1,j=0;p[i]=p[1]=3>q[j]=q[0]=2,s[1]=q[0]=2;j++;i=1,j=1;
    i=1,j=1;p[i]=p[1]=3<q[j]=q[1]=4,s[2]=p[1]=3;i++;i=2,j=1;
    i=2,j=1;p[i]=p[2]=5>q[j]=q[1]=4,s[3]=q[1]=4;j++;i=2,j=2;
    i=2,j=2;p[i]=p[2]=5<=q[j]=q[2]=5,s[4]=p[2]=5;i++;i=3,j=2;
    i=3,j=2;p[i]=p[3]=7>q[j]=q[2]=5,s[5]=q[2]=5;j++;i=3,j=3;
    i=3,j=3;p[i]=p[3]=7<q[j]=q[3]=8,s[6]=p[3]=7,i++;i=4,j=3;
    i=4,j=3;p[i]=p[4]=9>q[j]=q[3]=8,s[7]=q[3]=8,j++;i=4,j=4;
    i=4,j=4;p[i]=p[4]=10>q[j]=q[4]=9,s[8]=q[4]=9,j++;i=4,j=5
    s[9]=p[4]=10

原序列中两个值相同的数,排序后相对位置不发生变化,排序算法就是稳定的。

算法

#include<iostream>
using namespace std;
const int N = 1000010;
int n;// 数组元素个数
int q[N];//待排序的数组
int tmp[N];// 用来存放合并左右两边结果的数组
void merge_sort()
{
    // 当前区间只有一个数或者没有数
    if(l>=r) return ;
    // 确定分界点为数组中点
    int mid = l+r>>1;

    // 对左右两边进行递归排序
    merge_sort(q,l,mid);
    merge_sort(q,mid+1,r);
    
    // 将左右两边排好序的部分合并
    int k=0,i=l,j=mid+1;
    while(i<=mid&&j<=r)
    {
        if(q[i]<=q[j])
        {
           tmp[k]=q[i];
           k++;
           i++;
        }
        else
        {
            tmp[k]=q[j];
            k++;
            j++;
        }
     }
     
     //左半边有序数组没有循环完,剩余部分填到数组中
     while(i<=mid)
     {
         tmp[k++]=q[i++];
     }
     // 右半边数组没有循环完,剩余部分填到数组中
     while(j<=r)
     {
         tmp[k++]=q[j++];
     }
     for(i=l,j=0;i<=r;i++,j++)
     {
         q[i] = tmp[j];
     }
 }

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

时间复杂度

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值