算法与数据结构——大顶堆 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个高频元素

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

相关推荐
dtq04241 小时前
数据结构 - 堆
数据结构
nhdh8 小时前
B+树揭秘:MySQL索引核心原理全解析
数据结构·b树·mysql
海上小飞龙8 小时前
【KMP算法-下篇】同一道题:Java 库函数 2600 微秒,手写 KMP 16 微秒
java·开发语言·算法
青少儿编程课堂9 小时前
后缀自动机解析:本质不同子串与最长重复片段统计
c++·python·算法·bfs·信息学竞赛
朝朝辞暮i9 小时前
C++ 第 12 课:局部变量、作用域、变量生命周期
开发语言·c++·算法
乐迪信息10 小时前
港口船舶逆行怎么管?AI防爆摄像机搭载智能检测算法
大数据·人工智能·深度学习·算法·计算机视觉
Sirens.11 小时前
Java并发锁详解:六类锁策略与 synchronized 底层原理
java·前端·算法
和裕11 小时前
全纸结构重型纸箱能否满足 1 吨以上设备出口熏蒸豁免要求?通关合规性全解析
大数据·运维·网络·人工智能·算法
tangguofeng12 小时前
不带头结点的链队操作集(不含InitFlag)(C语言版)
算法
苏打豆13 小时前
CRISP源码阅读——基于ROS2力矩反馈控制器与速度加速度零空间
c++·线性代数·算法·矩阵·机器人