排序算法之归并排序

归并排序(Merge Sort)

归并排序是一种分治算法(Divide and Conquer),用于将一个无序数组或链表按照一定的顺序排序(通常是升序)。归并排序的核心思想是:将数组分为两个子数组,分别排序后再合并起来,最终得到一个有序的数组。

有两种方法实现归并排序

第一种是迭代法(自底向上归并法) ,第二种是递归法(自顶向下归并法)

迭代法

通过增加归并排序区间,多次小区间的归并,从而实现整个数组的排序

cpp 复制代码
void sort_(int*,int,int,int);
void merge_sort1(int* nums,int length)
{ 
    int* temp=new int[length];    
    for(int i=1;i<length;i*=2)       //不断增加归并区间i
    {   
        int index=0;                 //归并区间距离改变 从头开始迭代 
        
        /*可以分配2个i区间*/
        while(index+2*i<=length)      
        {
             index+=2*i;               
             sort_(nums,temp,index-2*i,index-i,index); //2*i的区间 归并左i区间和右i区间
        }

        /不足以分配2个i区间/
        if(index+i<length)  sort_(nums,temp,index,index+i,length);
    }  
    delete []temp; 
}
void sort_(int* nums,int* temp,int start,int mid,int end) //头闭尾开
{
    cout<<"归并的区间为"<<start<<" "<<mid<<" "<<end<<endl;
    int l=start;
    int r=mid;
    int index=0;
    while(index<end-start)
    {    
        if(l<mid&&(r==end||nums[l]<nums[r]))  //当左边小于右边或者右区间没有数据时
        {
            temp[index++]=nums[l++];   
        }  
        else temp[index++]=nums[r++];
    }  
    
    /*拷贝数据*/
    for(int i=0;i<end-start;i++)
    {
        nums[i+start]=temp[i];       
    }
}

通过改变归并区间大小不断的扫描整个数组

递归法

cpp 复制代码
void sort_(int*,int,int,int)
void merge_sort2(int* nums,int start,int end)
{
    if(end-start<2)  return;  //只有一个元素则退出递归
    int mid=(start+end)/2;
    merge_sort2(nums,start,mid);   //递归进入左半区间
    merge_sort2(nums,mid,end);     //递归进入右半区间
    sort_(nums,start,mid,end);     //归并当前的左右区间
}

void sort_(int* nums,int start,int mid,int end) //头闭尾开
{
    cout<<"归并的区间为"<<start<<" "<<mid<<" "<<end<<endl;
    int l=start;
    int r=mid;
    int index=0;
    int* temp=new int[end-start];
    while(index<end-start)
    {    
        if(l<mid&&(r==end||nums[l]<nums[r]))  //当左边小于右边或者右区间没有数据时
        {
            temp[index++]=nums[l++];   
        }  
        else temp[index++]=nums[r++];
    }  
    
    /*拷贝数据*/
    for(int i=0;i<end-start;i++)
    {
        nums[i+start]=temp[i];       
    }
    delete[]temp;
}

可以看出它是不断的递归进入自己的左右区间,递归到左右只有一个元素然后再向上合并

两种方法的时间复杂度都为O(nlog⁡n)

这里的迭代法的空间复杂度为O(n),递归法空间复杂度为 O(nlog⁡n),你可以传一个临时数组以达到O(n)并且可以减少new和delete带来的开销

进阶版:实现对链表的归并排序

相关推荐
minstbe18 分钟前
AI开发 - 算法基础 递归 的概念和入门(二)汉诺塔问题 递归的应用和使用注意 - Python
开发语言·python·算法
TANGLONG22243 分钟前
【初阶数据结构与算法】八大排序之非递归系列( 快排(使用栈或队列实现)、归并排序)
java·c语言·数据结构·c++·算法·蓝桥杯·排序算法
不想当程序猿_1 小时前
【蓝桥杯每日一题】与或异或——DFS
c++·算法·蓝桥杯·深度优先
就爱学编程1 小时前
力扣刷题:单链表OJ篇(下)
算法·leetcode·职场和发展
小白—人工智能1 小时前
有一个4*5的矩阵如下,要求编写程序计算总和与平均值,并找出其中值最大的那个元素输出,以及其所在的行号和列号。
数据结构·python·算法·矩阵
邂逅岁月1 小时前
滑不动窗口的秘密—— “滑动窗口“算法 (Java版)
算法·面试·求职招聘·创业创新·刷题
sunny-ll2 小时前
【C++】explicit关键字详解(explicit关键字是什么? 为什么需要explicit关键字? 如何使用explicit 关键字)
c语言·开发语言·c++·算法·面试
轩源源2 小时前
C++草原三剑客之一:继承
开发语言·数据结构·c++·算法·青少年编程·继承·组合
半盏茶香4 小时前
C语言勘破之路-最终篇 —— 预处理(下)
c语言·开发语言·c++·算法
pianmian18 小时前
贪心算法.
算法·贪心算法