一日一题:第四题---归并排序(和快排一样几乎!!)

讲解的视频-->快速排序与归并排序_哔哩哔哩_bilibili 

开始呢,我先sorry一下,最近比较忙,可能没有很仔细,不过,后期我会陆续更新讲解

小tip:

为什么,我说归并和快排差不多?因为看过我前期(直达-->快速排序) 的童鞋,就可以大致了解

快速排序的思想:

1.先找目标值(target),根据其排为左边都是“<=target”,右边都是“>=target”的状态 

2.将其继续分割,再递归上一步排序,一直分割到不能分割,就说明排好了

就利用的“分治回溯”的思想,而归并就更为明显

归并排序的思想:

1.先分割,分到不能再分,分到两个数组的元素都为1(两个指针指向相邻元素)

2.将连个指针作为队头进行比较,谁小谁放空数组,然后后移再与之前大的呢个指针的数比较,最后把排好序的原数组进行覆盖

说白了,就是切蛋糕切的不能再切了,再拿着每次同时切的两块比大小,谁小谁放前面,再把蛋糕按顺序拼好

题目描述

给定你一个长度为n的整数数列。

请你使用归并排序对这个数列按照从小到大进行排序。

并将排好序的数列按顺序输出。

输入格式

输入共两行,第一行包含整数 n。

第二行包含 n 个整数(所有整数均在1~10^9范围内),表示整个数列。

输出格式

输出共一行,包含 n 个整数,表示排好序的数列。

数据范围   

1≤n≤100000

输入样例:

5
3 1 2 4 5

输出样例:

1 2 3 4 5
#include<iostream>
#include<vector>
using namespace std;//格式记住就行
const int N=100010;//固定N的值
int n;
int temp[N];//定义全局变量
void merge_sort(int l,int r)//定义边界
{
    if(l>=r) return;//如果切到不能再切,就开始回溯判断
    int mid=l+r>>1;//相当于除2,但要速度快
    merge_sort(l,mid);//切蛋糕,每次切一半
    merge_sort(mid+1,r);
    
    // vector<int> g;
    int g[N];//定义一个空数组
    int k=0,a=l,b=mid+1;//定义两个指针,指向两个数组的头
    
    while(a<=mid&&b<=r)//在两个相邻数组中数字的是按顺序的,就从两个头开始比较,将两个顺序的数组合并
    {//其中一个超出范围就停下来
        if(temp[a]<=temp[b]) g[k++]=temp[a++];//如果第一个数组的第一个元素小,呢就把它先放在空数组里,同时向后移一位
        else g[k++]=temp[b++];//否则第二个数组第一个元素小,同理上
    }
    while(a<=mid) g[k++]=temp[a++];//这两个数组其中一个放完了,另一个还没放完,就继续
    while(b<=r) g[k++]=temp[b++];
    
    for(int i=l,j=0;i<=r;i++,j++)//将排好序的数组,赋予给原数组
        temp[i]=g[j];
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
        scanf("%d",&temp[i]);
        
    merge_sort(0,n-1);
    
    for(int i=0;i<n;i++)
        printf("%d ",temp[i]);
    return 0;
}

错误补充:我一直以为vector动态数组,可以直接赋值,然后我发现报错了,no!

通过实践(并没有去查具体资料,如果有其他大佬,知道求指正)

如果想直接赋值,就必须要像数组一样定义容器大小,如果不定义要用push_back

而且完全没必要我发现,直接定义一个数组,嘎嘎香,甚至更快!

更改后的代码 

void merge_sort(int l,int r)//定义边界
{
    if(l>=r) return;//如果切到不能再切,就开始回溯判断
    int mid=(l+r)/2;//相当于除2,但要速度快
    merge_sort(l,mid);//切蛋糕,每次切一半
    merge_sort(mid+1,r);
    
    vector<int> g;
    // int g[N];//定义一个空数组
    int k=0,a=l,b=mid+1;//定义两个指针,指向两个数组的头
    
    while(a<=mid&&b<=r)//在两个相邻数组中数字的是按顺序的,就从两个头开始比较,将两个顺序的数组合并
    {//其中一个超出范围就停下来
        if(temp[a]<=temp[b]) 
        // g[k++]=temp[a++];//如果第一个数组的第一个元素小,呢就把它先放在空数组里,同时向后移一位
            g.push_back(temp[a++]);
        else 
        // g[k++]=temp[b++];//否则第二个数组第一个元素小,同理上
            g.push_back(temp[b++]);
        
    }
    while(a<=mid) 
    // g[k++]=temp[a++];//这两个数组其中一个放完了,另一个还没放完,就继续
        g.push_back(temp[a++]);
    while(b<=r) 
    // g[k++]=temp[b++];
        g.push_back(temp[b++]);
    for(int i=l,j=0;i<=r;i++,j++)//将排好序的数组,赋予给原数组
        temp[i]=g[j];
}

心得:(就是废话) O(∩_∩)O

哎,马上要蓝桥杯了 ,最近压力是真的大。早就知道自己差的好远,走弯路太多了,而且还是不勤奋,感觉这次去就是给各位大佬当垫脚石了(心甘情愿),所以我决定要持续更新了,为明年备战吧,算是,其实上大学才发现,躺着不动很舒服,但凡你走起来,就会遇到跑的人,看着他们的背影,你又会感叹,为什么自己在走,道阻其长吧!/(ㄒoㄒ)/~~

欢迎来到一日一题的小菜鸟频道,睡不着就看看吧

跟着小张刷题吧!
跟着小张刷题吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值