在阅读这篇题解之前,你需要明白完全二叉树的概念,百度一下
二叉堆是一种寻找最大值最小值十分高效的数据结构。
理论
普通二叉堆主要分为两种:
- 小根堆
- 大根堆
特性:二叉堆的每一个节点都比它的子节点大(大根堆)或小(小根堆)。
时间复杂度:插入删除为logn,去最大最小为常数。
为了保持这个特性,我们需要在插入删除时互换节点。
插入(小根堆)
- 将节点插入到最后一个位置。
- 与双亲节点比较,如果比上一个节点小就互换。
- 重复2,直到双亲节点比节点小,或者节点位于根节点。
删除(小根堆)
删除默认都是删除堆的根节点。
- 删除根节点。
- 使用最后一个节点来补根节点的位置。
- 与子节点互换调整,保持特性。应该选择左右节点中小的来换。
小灰的文章
可视化
实现
在实现之前,我们来复习下完全二叉树的性质:
如果对一棵有n个结点的完全二叉树的结点按层序编号, 则对任一结点i (1≤i≤n) 有:
- 如果i=1, 则结点i是二叉树的根, 无双亲;如果i>1, 则其双亲节点是结点i/2
- 如果2i>n, 则结点i无左孩子, 否则其左孩子是结点2i;
- 如果2i+1>n, 则结点i无右孩子, 否则其右孩子是结点2i+1.
由于我们每一次插入和删除,都是在堆的最后一个节点的位置调整的,所以整个堆可以填充整个数据(不会出现稀疏状况),使用完全二叉树的特性可以快速定位双亲节点和子节点,所以,使用vector不会浪费空间
但是vector互换节点的速度并不快,可以考虑用一个临时变量存储,直到找到一个合适的节点,只进行一次互换(见我的代码)
我的实现 (小根堆)
//
// Created by Cat-shao on 2021/1/15.
// 小根堆模板
#include <vector>
using namespace std;
template<typename T>
class heap // 小根堆模板
{