LeetCode:实现最大堆

优先队列(priority queue)可以在O(1)时间内获取最大值,并且在0(logn)时间内取出最大值或插入任意值.
优先队列常常用堆(heap)来实现,堆是一个完全二叉树,其每个节点的值总是大于等于或小于等于子节点的值.实际
实现堆时,通常用一个数组而不是指针建立一盒树.这是因为堆是完全二叉树,所以利用数组表示时,
(1)若根节点的位置为0,则位置i的节点的父节点一定为(i-1)/2,而它的两个字节点的位置一定为2i+1和2i+2.
(2)若根节点的位置为1,则位置i的节点的父节点一定为i/2,而它的两个字节点的位置一定为2i和2i+1.
堆的实现方式为:
如果一个节点有两个子节点,总是交换最大的子节点.
(1)上浮
如果一个节点比父节点大,那么需要交换这两个节点,交换后还可能比它新的父节点大,因此需要不断地进行比较和交换
操作.
(2)下浮
类似地,如果一个节点比父节点小,也需要不断地向下进行比较和交换操作.

make_heap函数默认最大堆,less<int>(),利用vector实现最大堆
#include <iostream>
#include <vector>

using namespace std;

//根节点初始下标为1
class MaxHeap{
public:
    //获取最大值
    int top(){
        return heap[0];
    }
    
    //插入任意值,把新的数字放在最后一位,然后上浮
    void push(int k){
        heap.push_back(k);
        swim(heap.size()-1);//维持最大堆    
    }

    //删除最大值,把最后一个数字挪到开头,然后下沉
    void pop(){
        heap[0]=heap.back();
        heap.pop_back();//移除
        sink(0);//维持最大堆
    }

    //打印
    void print(){
        for(auto& h:heap){
            printf("%d ",h);
        }
    }

private:
    //上浮
    void swim(int pos){
        while(pos>=1&&heap[pos/2]<heap[pos]){
            swap(heap[pos/2],heap[pos]);
            pos/=2;
        }
    }

    //下沉
    void sink(int pos){
        int N=heap.size();
        while(2*pos<=N){
            int i=2*pos+1;
            if(i<N&&heap[i]<heap[i+1]) //选择子节点较大者
               ++i;
            if(heap[pos]>=heap[i])
               break;
            swap(heap[pos],heap[i]);
            pos=i;
        }
    }
private:
    vector<int> heap;
};

int main(int argc,char* argv[]){
    vector<int> nums={0,1,2,3,4,8,3,9,5};
    MaxHeap heap;
    for(auto& n:nums){
        heap.push(n);
    }
    heap.print();
    cout<<endl;
    cout<<heap.top()<<endl;
    heap.pop();
    heap.print();
    return 0;
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路上的追梦人

您的鼓励就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值