归并排序思想及实现

归并排序思想及实现

  • 主要思想

    归并排序主要使用的是分治的思想,但其操作的重点并不在于分治,而在于归并。

    所以接下来我们先了解一下归并这个操作,当熟练掌握归并的操作以后,归并排序也就很好掌握。

  • 归并

    如果我们现在分别有两个有序的序列

    1,4,6,7,9

    2,5,8,10,12,15

    我们对这两个有序序列进行归并的操作即:将这两个有序序列合并成一个有序序列

    接下来介绍完成归并的一般步骤

    • 设置位置指针

      我们暂且称上述两个序列为A序列和B序列,我们定义两个指针PointaPointb来指向这两个序列的头部元素

      例如Pointa指向A序列的头部元素1

      同理Pointb指向B序列的头部元素2

    • 移动指针进行比较来完成合并

      我们需要再定义一个序列C来存放AB合并的结果

      • 在两个指针的当前位置进行比较

        比如初始时,Pointa指向1,且Pointb指向2,此时明显1<2所以先将Pointa指针指向的元素值放入C中,并将Pointa指针移到下一位,也就是4

        接下来同样比较两个指针所指向的数值,又因为2<4所以我们将Pointb指向的元素放入C中,并将指针后移一位

      • 直到一个序列已经完全放入C

        这时将另一个还有剩余的序列剩下的元素直接放入C中即可

    程序代码:

    vector<int> Merge(vector<int>& a,vector<int>& b){
        
        vector<int> ans; //保存答案
        
        //定义指向两个序列的指针
        int Pointa=0;
        int Pointb=0;
        
        while(Pointa<a.size()&&Pointb<b.size()){
            //比较两个序列当前指针所指元素 并选择将谁放入答案序列中
            if(a[Pointa]<=b[Pointb]){
                ans.push_back(a[Pointa]);
                Pointa++;
            }
            else{
                ans.push_back(b[Pointb]);
                Pointb++;
            }
            
        }
        
        //找出仍有剩余的序列 并将其剩余元素全部放入答案序列中
        while(Pointa<a.size()) ans.push_back(a[Pointa++]);
        while(Pointb<b.size()) ans.push_back(b[Pointb++]);
        
        return ans;
    
    }
    
  • 分治

    在我们理解了归并的操作以后,就可以利用分治的思想来对无序数组进行排序

在这里插入图片描述

这里我们利用二分法将无序序列分解到单个元素时,这些单个元素就可以视作一个有序的序列,接下来我们只需要一步一步的把这个序列进行上述的归并操作来合并成长的有序序列,再返回上去,就可以得到完整有序的序列,具体操作如下:

在这里插入图片描述

每一次进行一个Merge操作,最终得到有序序列

程序代码:

vector<int> Sort(vector<int>& a,int lo,int hi){
    //这里的lo和hi分别代表当前序列的最低下标和最高下标

    vector<int> ans;
    //用来记录答案
    
    if(lo==hi){
        //当分解到单个数的时候 默认已经有序 返回该序列
        ans.push_back(a[lo]);
        return ans;
    }
    
    int mid=(lo+hi)>>1; //计算出中间值
    
    //通过递归的方式将左右两边排好序
    vector<int> left=Sort(a,lo,mid);
    vector<int> right=Sort(a,mid+1,hi);
    
    //整合左右两侧的有序序列成一个有序序列并返回
    return Merge(left,right);

}

至此,归并排序大体完成

  • 总代码

    #include<iostream>
    #include<vector>
    
    using namespace std;
    
    vector<int> Merge(vector<int>& a,vector<int>& b){
        vector<int> ans; //保存答案
        int Pointa=0;
        int Pointb=0;
        while(Pointa<a.size()&&Pointb<b.size()){
            if(a[Pointa]<=b[Pointb]){
                ans.push_back(a[Pointa]);
                Pointa++;
            }
            else{
                ans.push_back(b[Pointb]);
                Pointb++;
            }
            
        }
        while(Pointa<a.size()) ans.push_back(a[Pointa++]);
        while(Pointb<b.size()) ans.push_back(b[Pointb++]);
        return ans;
    
    }
    
    vector<int> Sort(vector<int>& a,int lo,int hi){
    
        vector<int> ans;
        if(lo==hi){
            ans.push_back(a[lo]);
            return ans;
        }
        int mid=(lo+hi)>>1;
        vector<int> left=Sort(a,lo,mid);
        vector<int> right=Sort(a,mid+1,hi);
        return Merge(left,right);
    
    
    }
    
    int main(){
    
        vector<int> a;
        int n,x;
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>x;
            a.push_back(x);
        }
        vector<int> ans=Sort(a,0,a.size()-1);
        for(int i=0;i<ans.size();i++) cout<<ans[i]<<" ";
        cout<<endl;
    }
    
    

结束

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值