归并排序 分治递归

在这里插入图片描述
归并排序主要用了分治与递归的思想,前期划分,后期合并,时间复杂度为nlogn
1、确定分界点 mid=(l+r)/2
2、递归排序
3、归并 — 合二为一
话不多说,上代码

#include<stdio.h>
#include<stdlib.h>//分配内存

void print_arr(int arr[],int n)//辅助函数,打印数组
{
    for(int i=0;i<n;i++)
        printf("%d",arr[i]);
    putchar('\n');
}

//合并
void merge(int arr[],int tempArr[],int left,int mid,int right)
{
    int l_pos=left;//标记左半区第一个未排序的元素
    int r_pos=mid+1;//标记右半区第一个未排序的元素
    int pos=left;//临时数组元素的下标

    //合并
    while(l_pos<=mid&&r_pos<=right)
    {
        if(arr[l_pos]<arr[r_pos])
            tempArr[pos++]=arr[l_pos++];
        else
            tempArr[pos++]=arr[r_pos++];
    }
    //合并左半区剩余的元素
    while(l_pos<=mid)
        tempArr[pos++]=arr[l_pos++];
    //合并右半区剩余的元素
    while(r_pos<=right)
        tempArr[pos++]=arr[r_pos++];
    //把临时数组中合并后的元素复制回原来的数组
    while(left<=right)
    {
        arr[left]=tempArr[left];
        left++;
    }
}

//归并排序
void msort(int arr[],int tempArr[],int left,int right)
{
    //如果只有一个元素,那么就不用继续划分了
    //因为一个元素的区域,它本身就是有序的
    if(left<right)
    {
        //找中间点
        int mid=(left+right)/2;
        //递归划分左半区
        msort(arr,tempArr,left,mid);
        //递归划分右半区
        msort(arr,tempArr,mid+1,right);
        //归并已经排序好的部分
        merge(arr,tempArr,left,mid,right);
    }
}

//归并排序的入口
//主要进行辅助数组的分配和回收
void merge_sort(int arr[],int n)
{
    //分配一个辅助数组
    int *tempArr=(int*)malloc(n*sizeof(int));
    if(tempArr)//辅助数组分配成功
    {
        msort(arr,tempArr,0,n-1);
        free(tempArr);//使用完,释放空间
    }
    else
        printf("error:failed to allocate memory");

}

int main(int argc,char const*argv[])
{
    int arr[]={9,5,2,7,12,4,3,1,11};
    int n=9;
    print_arr(arr,n);

    merge_sort(arr,n);
    print_arr(arr,n);
    return 0;
}

这里还有一个y总给的简洁版

#include<iostream>
using namespace std;
const int N=1000010;
int n;
int a[N],temp[N];
void merge_sort(int q[],int l,int r)
{
    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])temp[k++]=q[i++];
       else temp[k++]=q[j++];

    while(i<=mid)temp[k++]=q[i++];//处理多余元素
    while(j<=r)temp[k++]=q[j++];

    for(i=l,j=0;i<=r;i++,j++)q[i]=temp[j];//把排序好的复制回元素组
    //排序的区间是从 l 开始的,排完序后,将临时数组中的值拷会原数组中对应位置。
}

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)scanf("%d",&a[i]);
    merge_sort(a,0,n-1);//归并排序merge_sort()内部 左右区间分解到只剩一个数 然后进行合并 往上传递

    for(int i=0;i<n;i++)
       printf("%d ",a[i]);

    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值