- gf24240 的博客
《梦溪笔谈·笔记》2025/7/25:哈夫曼树&二叉搜索树
- 2025-7-26 13:36:49 @
前言
这篇 blog 可能只能讲理论了。(只因这两个都太难了)
哈夫曼树
哈夫曼树可以使用 优先队列 实现。所以要先将优先队列。
优先队列
优先队列其实是提高组的内容。
优先队列是 STL 的容器之一。它实际上是一个——用 D 老师的话来说——类似栈的“麻袋”,内部使用二叉树实现,和队列一点关系都没有。如图:

先说优先队列的一些信息:
- 优先队列实际上类似栈;
- 优先队列内部使用二叉树(还是二叉堆?)实现;
- 正因为(2),所以优先队列能够自动排序;
- 优先队列默认从大到小排序。
头文件
和队列一样。
#include <queue>
定义
这个就很长了。
priority_queue <int> 队列名;
插入
这些都和栈一样了。
q.push(x);
弹出
q.pop();
队首
q.top()
从小到大
这有两种方法:
- 压入负数,弹出 -负数;
- 正规方法。
方法1: 只需要在压入和弹出时都加上负号:
#include <queue>
#include <iostream>
using namespace std;
priority_queue <int> q;
int n, x;
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> x;
q.push(-x);
}
while (!q.empty())
{
cout << -q.top() << "\n";
q.pop();
}
return 0;
}
方法2: 需要自定义比较函数或用 greater<>
;
自定义比较函数: 这部分比较困难,也不像 sort
的比较函数。所以这里只用比较器。
比较器: 这只需要把定义改一下:
#include <queue>
#include <iostream>
using namespace std;
priority_queue <int, vector <int>, greater<int>> q;
int n, x;
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> x;
q.push(x);
}
while (!q.empty())
{
cout << q.top() << "\n";
q.pop();
}
return 0;
}
使用优先队列实现 hfm
- 先把所有东西(结构体{权值,序号等})压入priority_queue;
- 弹出前两个最小的;
- 根据最小的生成new node;
- 递归2、3步
- DFS每一个节点,用string存储编码;
二叉查找树/二叉搜索树(BST)
查找
二叉查找树的中序遍历是有序的 ,它的查找和二分查找类似。
- 如果树为空,返回-1
- 将根节点和x对比
- 如果x==T->data,说明找到了,返回根节点
- 如果x < T->data,递归查找左子树
- 反之递归查找右子树。
平均查找时间
插入
1)如果二叉查找树为空,创建新节点 2)如果不为空:
- 如果x<T-data,往左边插
- 反之往右边插
创建
相当于不停地插入
删除
有三种情况(要删除节点的):
- 左子树为空
- 右子树为空
- 左右子树都不为空
左/右子树为空
直接覆盖要删除的节点
都不为空
选择要删除的左儿子的最右后代或右儿子的最左后代代替这个节点。
卡特兰数
有n个节点,可以构造成多少中二叉树(或 n 个节点入栈,有多少中出站顺序):1,1, 2,5,14,42,132,429……