超快排序的N种答法

本文深入讲解了归并排序和堆排序两种高效的排序算法,详细介绍了它们的实现原理和步骤,并提供了C++代码示例,适合对算法性能有高要求的读者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

超快的排序——
N种答法

众所周知,在oj里一个重要的算法是排序
入门级的:冒泡、选择、箱、插入
进阶级的:快速、归并、堆、桶
当遇到比较大的数据要排序时,入门级大多都不管用了
冒泡、选择超过时间限制
箱超过空间限制
插入还需要练得恰到好处并且找规律
否则也会超过时间限制
那么这里分享两种排法
目录
1.归并排序
2.堆排序

1.归并排序
思路:
归并排序的基本条件是将两个有序序列合并
那么怎么找到两个有序序列呢?
我们可以用递归二分的方法
当一个序列只有一个元素时
默认它是有序的
然后回到这个回溯的过程
将两个有序序列合并
最终合并成一个有序序列
将答案输出

#include<iostream>
using namespace std;
int a[100005],c[100005]; 
void merge(int l,int r)
{
    if(l>=r)  return ;//当他只剩下一个或不及一个元素时默认有序,返回 
    int s=l,mid=(l+r)/2,x=l,y=mid+1;//二分的mid 
    merge(l,mid);//回溯 
    merge(mid+1,r);
    //此时回溯结束,默认a数组前面到mid有序,mid+1到结束有序 
    while(x<=mid&&y<=r)//开始合并前后,x和y是指针 
    {
        if(a[x]>a[y])//如果前面的大于后面,取前面 
        {
            c[s]=a[x];
            x++;//指针向后挪一位 
        }
        else//否则取后面 
        {
            c[s]=a[y];
            y++;
        }
        s++;
    }
    while(x<=mid)//如果前面还有未取的全部放到后面 
    {
        c[s++]=a[x];
        x++;
    }
    while(y<=r)//如果不是前面就是后面 
    {
        c[s++]=a[y];
        y++;
    }
    for(int i=l;i<=r;i++)  a[i]=c[i];//把c数组赋值回a数组 
}
int main()
{
    int n,i;
    cin>>n;
    for(i=1;i<=n;i++)  cin>>a[i];
    merge(1,n);//开始排序 
    for(i=n;i>=1;i--)  cout<<a[i]<<" ";
    return 0;
}

2.堆排序
堆排序原理为把数组看做一个堆
先建设一个有序的堆
然后把堆顶的值取出
放置ans数组
把堆顶移除
然后维护下一个堆顶
如此循环

#include <iostream>
using namespace std;
int a[100005],n,s;
void up(int x)
{
    if(x==1||a[x]<=a[x/2])  return ;//如果是堆顶或是已达成顺序,返回 
    swap(a[x],a[x/2]);//否则把父节点和子节点交换 
    up(x/2);//往上接着换 
    return ;
}
void down(int x)
{
    int l=2*x,r=l+1,da=x;
    if(l<=s&&a[l]>a[da])  da=l;//将da替换成最大值 
    if(r<=s&&a[r]>a[da])  da=r;
    if(da!=x)
    {
        swap(a[x],a[da]);//如果da改变了,交换 
        down(da);//继续 
    }
}
int main(int argc, char** argv)
{
    int i;
    cin>>n;
    s=n;//当前的堆大小 
    for(i=1;i<=n;i++)
    {
        cin>>a[i];//输入数组,建造最小堆 
        up(i);
    }
    for(i=n;i>1;i--)
    {
        swap(a[1],a[s]);//先将堆顶和堆底交换 
        s--;//堆的大小减一 
        down(1);//维护新堆顶 
    }
    for(i=1;i<=n;i++)  cout<<a[i]<<" ";
    return 0;
}

不见不散,咱们下期再见~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值