算法-堆排序

题目一

 解题思路

堆排序(降序)的核心思想:

     因为建小堆可以选出最小的数即根节点,我们将每次建好的小堆的最后一个叶子节点和根节点进行交换,交换后不把最后一个数看作堆里的数据,此时根的左右子树依旧是大堆,然后我们再用向下调整算法选出次小的如此循环直到堆里剩一个数结束

在这里插入图片描述

 i为什么从n/2开始down

变量与边界

down操作中,u负责存储原数,比较时要以用u为准,t在比较过程中可能被修改。 

堆的物理结构为数组,实现时为了方便计算,从下标1开始存储。

代码模板

#include<iostream>
using namespace std;
const int N=1e5+10;
int n,m;
int q[N],qsize;

void down(int u)
{
    int t=u;
    if(u*2<=qsize&&q[t]>q[u*2])t=u*2;
    if(u*2+1<=qsize&&q[t]>q[u*2+1])t=u*2+1;
    if(t!=u)
    {
        swap(q[u],q[t]);
        down(t);
    }
}
int main()
{
    cin>>n>>m;
    qsize=n;
    for(int i= 1;i<=n;i++)
        cin>>q[i];
    for(int i=n/2;i;i--)
        down(i);
    while(m--)
    {
        cout<<q[1]<<" ";
        q[1]=q[qsize--];
        down(1);
    }
        
    return 0;
}

题目二

 解题思路

 依旧是使用数组模拟堆,核心思路是用另外两个数组表示堆到顺序,顺序到堆的映射关系

代码注意点:

hsize表示堆下标,index表示顺序下标,修改数值时要注意使用的下标;

修改第K个数时,先通过顺序数组求出K数对应的堆下标,再在堆中进行修改

代码模板


#include<iostream>
using namespace std;
const int N=1e5+10;
int ph[N],hp[N],h[N],n;//ph(point->heap)可以获得第几个插入的元素现在在堆里的哪个位置
                        //hp(heap->point)可以获得在堆的第n个元素存的是第几个插入的元素
int index,hsize;

void h_swap(int i,int j)
{
    swap(ph[hp[i]],ph[hp[j]]);
    swap(hp[i],hp[j]);
    swap(h[i],h[j]);
}
void down(int u)
{
    int t=u;
    if(u*2<=hsize && h[u*2]<h[t])t=u*2;
    if(u*2+1<=hsize && h[u*2+1]<h[t])t=u*2+1;
    if(u!=t)
    {
        h_swap(u,t);
        down(t);
    }
}

void up(int u)
{
    while(u/2&&h[u/2]>h[u]){
        h_swap(u,u/2);
        u>>=1;
    }
}



int main()
{
    scanf("%d",&n);
    while(n--)
    {
        string t;
        int k,x;
        cin>>t;
        if(t=="I")//插入一个数 x
        {
            cin>>x;
            index++; hsize++;
            ph[index]=hsize,hp[hsize]=index;
            h[hsize]=x;
            up(hsize);
        }
        else if(t=="PM")//输出当前集合中的最小值;
        {
            cout<<h[1]<<endl;
            
        }
        else if(t=="DM")//删除当前集合中的最小值(数据保证此时的最小值唯一)
        {             
            h_swap(1,hsize);
            hsize--;
            down(1);
        }
        else if(t=="D")//删除第 k个插入的数;
        {
            cin>>k;
            k=ph[k];
            h_swap(k,hsize);
            hsize--;
            up(k),down(k);
        }
        else if(t=="C")//修改第k个插入的数,将其变为 x;
        {
            cin>>k>>x;
            k=ph[k];
            h[k]=x;
            up(k),down(k);
        }
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值