最大堆的简单实现

一.什么是最大堆?
  最大堆的每一个节点的值都大于它的子节点的值.
在这里插入图片描述
二.如何实现最大堆?

堆的插入
首先插入到末尾
在这里插入图片描述

与父结点进行比较如果大于则与父结点交换位置

在这里插入图片描述

堆中取出元素,让堆末尾的元素放入堆的首部,和相邻子类进行比较,将其中较大的数字和父类指针进行交换

在这里插入图片描述

在这里插入图片描述
三.代码实现

采用vector 和 unordered_map 来进行实现

在代码中有详细的解释

#include <unordered_map>
#include <utility>
#include <vector>
class Priority_queue {
public:
    using pair = std::pair<size_t, uint64_t>;
    Priority_queue() = default;
    Priority_queue& operator=(const Priority_queue& other) = delete;
    bool Contains(size_t key) const {
        return m_pointer.find(key) != m_pointer.end();
    	//判断相应的键在堆中是不是存在
    }
    
    size_t GetSize() const {
        return m_heap.size(); // 返回堆的大小
    }
    const pair& Top() const {
        return m_heap.front(); // 返回堆顶
    }
    void Push(size_t key, uint64_t value) {
        if (Contains(key)) { // 这个key 在不在堆中
            const size_t index = m_pointer.at(key);
            //找到在堆中对应的位置
  			//直接进行更新
            m_heap.at(index).second = value;
            //进行上滤操作
            Heap_Up(index);
            //可能比之前结点小 //那么进行下滤
            //进行下滤比较
            Heap_Down(index);
        } else {
           //不存在的话,在堆最后放入结点,进行上滤操作
            const size_t index = m_heap.size();
            m_pointer[key] = index;
            m_heap.emplace_back(key, value);
            Heap_Up(index);
        }
    }
    void Pop() {
    	//首先从哈希map中删除堆顶元素的索引
        m_pointer.erase(m_heap.front().first);
        m_heap.front() = m_heap.back();
        m_heap.resize(m_heap.size() - 1);
        //末尾的第一个元素放对顶
        constexpr size_t index = 0;
        m_pointer[m_heap.front().first] = index;
        //
        Heap_Down(index);
        //进行下滤
    }
private:
    void Heap_Up(size_t index) {
    	//上滤
        while (index != m_root) {  // 如果索引到根结点退出
            auto&& parent = Parent(index);
            //获取父亲结点的索引
            auto&& value = m_heap.at(index).second;
            //当前结点的值
            auto&& parent_value = m_heap.at(parent).second;
            //获取父结点的值
            if (parent_value > value)
                break;
            Swap(index, parent);
           //索引和值的交换
            index = parent;
        }
    }
    void Heap_Down(size_t index) {
    	//下滤
        while (index < m_heap.size()) {
            auto&& child = Leftchild(index);
            //获取孩子的Index
            //超出堆的范围
            if (child >= m_heap.size()) {
                break;
            }
            //左孩子和右孩子进行比较,选出最大的
            if (child + 1 < m_heap.size()) {
                child = (m_heap.at(child + 1).second > m_heap.at(child).second) ? child + 1 : child;
            }
            
            if (m_heap.at(index).second > m_heap.at(child).second)
                break;
            //交换
            Swap(index, child);
            index = child;
        }
    }

    //堆中元素的交换
    //交换堆的值和hashmap中的索引
    void Swap(size_t first, size_t second) {
        auto&& pair_first = m_heap.at(first);
        auto&& pair_second = m_heap.at(second);
        m_pointer[pair_first.first] = second;
        m_pointer[pair_second.first] = first;
        std::swap(m_heap[first], m_heap[second]);
    }
 	//返回父结点的地址信息
    inline size_t Parent(size_t index) const {
        return (index - 1) / 2;
    }
	//返回子结点的地址信息
    inline size_t Leftchild(size_t index) const {
        return index * 2 + 1;
    }

    std::vector<pair> m_heap;
    std::unordered_map<size_t, size_t> m_pointer;
    static constexpr size_t m_root = 0;  // 堆的根为0
    };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值