算法与数据结构——大顶堆 and 小顶堆

0.定义

大顶堆 :树中所有根节点必须大于等于其左儿子和右儿子,因此根节点是最大值。
小顶堆:树中所有根节点必须大于等于其左儿子和右儿子,因此根节点是最小值。

1.自己实现大顶堆和小顶堆

cpp 复制代码
#pragma once

#include <vector>
#include <iostream>
#include <assert.h>
using namespace std;


// 小顶堆
template <class T>
struct myGreater
{
    bool operator()(const T &left, const T &right) { return left > right; }
};

// 大顶堆
template <class T>
struct myLess
{
    bool operator()(const T &left, const T &right) { return left < right; }
};

template <class T, class Compare = myLess<T>>
class myHeap
{
public:
    myHeap() {}

    myHeap(vector<T> vec)
    {
        _array.reserve(vec.size());
        _array.assign(vec.begin(), vec.end());

        // 建堆
        for (int i = _array.size() / 2 - 1; i >= 0; i--)
            AjustDown(i);
    }

    bool empty() const { return _array.empty(); }

    size_t size() const { return _array.size(); }

    T &top()
    {
        assert(!_array.empty());
        return _array[0];
    }

    void push(T elem)
    {
        _array.push_back(elem);
        AjustUp(_array.size() - 1);
    }

    void pop()
    {
        assert(!_array.empty());
        swap(_array[0], _array[_array.size() - 1]);
        _array.pop_back();
        AjustDown(0);
    }

private:
    void AjustDown(int parent)
    {
        int child = parent * 2 + 1; // left child idx
        while (child < _array.size())
        {
            if (child + 1 < _array.size() && cmp(_array[child], _array[child + 1]))
                ++child;

            if (cmp(_array[parent], _array[child]))
            {
                swap(_array[parent], _array[child]);
                parent = child;
                child = 2 * parent + 1;
            }
            else
                break;
        }
    }

    void AjustUp(int child)
    {
        int parent = (child - 1) / 2;
        while (parent >= 0)
        {
            if (cmp(_array[parent], _array[child]))
            {
                swap(_array[parent], _array[child]);
                child = parent;
                parent = (child - 1) / 2;
            }
            else
                break;
        }
    }

    vector<T> _array;
    Compare cmp;
};

template <typename T>
using maxHeap = myHeap<T,myLess<T>>;

template <typename T>
using minHeap = myHeap<T,myGreater<T>>;


int main()
{
    vector<int> a = {11, 10, 13, 12, 16, 18, 15, 17, 14, 19};
    myHeap<int> hp1(a); 
    cout << hp1.top() << endl;
    hp1.push(90);
    hp1.push(900);
    cout << hp1.top() << endl;
    hp1.pop();
    hp1.pop();
    hp1.pop();
    hp1.pop();
    hp1.pop();
    hp1.pop();
    hp1.pop();

    // system("pause");
    return 0;
}

比较重要的是:

  1. 仿函数的写法:大顶堆是left<right,命名为Less;小顶堆是left>right,命名为Greater。
  2. 堆调整是cmp(_array[parent], _array[child])或者cmp(_array[left_child], _array[right_child]),这个顺序是和第一步仿函数的写法对应。这个过程详细描述如下:(以Less为例),Less是left<right写法,
    第一步,进行左孩子取值 < 右孩子取值比较,如果为真,使用右孩子与父节点比较,否则使用做孩子与父节点比较(见 AjustDown 函数体内 while 循环后第一个 if 语句);
    第二步,在父节点取值 < 孩子节点取值时,交换父和子,于是取值较大的孩子节点成为根节点(也就是说这个堆是大顶堆)。

2.STL优先队列

给自己打个广告:找工作准备刷题day1 栈与队列

优先队列练手:Leetcode347.前K个高频元素

自己写完以后更好地理解 为什么 小顶堆 的仿函数 是 >

相关推荐
Greedy Alg4 小时前
LeetCode 142. 环形链表 II
算法
睡不醒的kun4 小时前
leetcode算法刷题的第三十二天
数据结构·c++·算法·leetcode·职场和发展·贪心算法·动态规划
先做个垃圾出来………5 小时前
残差连接的概念与作用
人工智能·算法·机器学习·语言模型·自然语言处理
SuperCandyXu6 小时前
P3205 [HNOI2010] 合唱队-普及+/提高
c++·算法·洛谷
_OP_CHEN6 小时前
数据结构(C语言篇):(十二)实现顺序结构二叉树——堆
c语言·数据结构·算法·二叉树·学习笔记··顺序结构二叉树
Yingjun Mo7 小时前
1. 统计推断-基于神经网络与Langevin扩散的自适应潜变量建模与优化
人工智能·神经网络·算法·机器学习·概率论
地平线开发者7 小时前
征程 6 | 灰度图部署链路介绍
算法·自动驾驶
地平线开发者8 小时前
手撕大模型|KVCache 原理及代码解析
算法·自动驾驶
cellurw8 小时前
EDID 数据结构解析与编辑工具:校验和计算、厂商/设备名编解码、物理地址读写、颜色与时序信息提取
数据结构
共享家95279 小时前
经典动态规划题解
算法·leetcode·动态规划