特殊树
特殊树
完全二叉树的定义与基本性质、数组表示法;哈夫曼树的定义和构造、哈夫曼编码;二叉搜索树的定义和构造。
概念
完全二叉树:除最后一层外各层满,最后一层从左到右连续填;n 个结点时可紧凑存入数组,下标 i 的父为 ⌊i/2⌋,左子 2i、右子 2i+1。哈夫曼树:带权路径长度最小的二叉树,构造时每次合并权值最小的两棵;用于变长编码,高频字符短码、低频长码,且任一编码不是另一编码前缀。二叉搜索树(BST):左子树键值 < 根 < 右子树;中序遍历得有序序列。与 cspj.ds.tree:特殊树都是树,但加了形状或权值约束;与 cspj.ds.binary-tree:本叶不考一般遍历还原,而考完全二叉树计数/高度、哈夫曼带权路径长或编码长度、BST 插入查找性质。
CSP-J 常考
cspj-r1-2019第 8 题:给定二叉树形态,顺序存储(根下标 1)时数组最大下标至少为多少。cspj-r1-2020第 12 题:61 个结点的完全二叉树高度(根高度为 1)。cspj-r1-2022第 7 题:按字母频率构造哈夫曼编码,求某字母的编码位数。cspj-r1-2022第 8 题:完全二叉树数组下标 9 的结点有兄弟且有两个孩子,求兄弟与右孩子下标。cspj-r1-2025第 4 题:五个权值构造哈夫曼树,求带权路径长度(WPL)。
#include <queue>
#include <vector>
using namespace std;
// 哈夫曼 WPL:每次取最小两权合并
int huffmanWpl(vector<int> w) {
priority_queue<int, vector<int>, greater<int>> pq(w.begin(), w.end());
int ans = 0;
while (pq.size() > 1) {
int a = pq.top(); pq.pop();
int b = pq.top(); pq.pop();
ans += a + b;
pq.push(a + b);
}
return ans;
}
易错点
- 完全二叉树高度:n 个结点时 h=⌊log2n⌋+1(根高 1),与「满二叉树」层数公式不要混用。
- 哈夫曼构造:先合并最小两个,新结点权为两者之和;WPL 是各叶子权×深度之和,不是简单相加所有权值。
- 数组下标 9 的兄弟是 8 还是 10:同层相邻偶奇配对,i 与 i±1 互为兄弟(i>1)。
- BST 插入重复键、删除结点后的中序有序性——初赛若考,先画小例子再选。
一棵二叉树如右图所示,若采用顺序存储结构,即用一维数组元素存储该二叉树中的结点(根结点的下标为 1,若某结点的下标为 i,则其左孩子位于下标 2i 处、右孩子位于下标 2i+1 处),则该数组的最大下标至少为()。
独根树的高度为 1。具有 61 个结点的完全二叉树的高度为( )。
如果一棵二叉树只有根结点,那么这棵二叉树高度为 1。请问高度为 5 的完全二叉树有 ( )种不同的形态?
假设字母表 {a,b,c,d,e} 在字符串出现的频率分别为 10%,15%,30%,16%,29%。若使用哈夫曼编码方式对字母进行不定长的二进制编码,字母 d 的编码长度( )位。
一棵有 n 个结点的完全二叉树用数组进行存储与表示,已知根结点存储在数组的第 1 个位置。若存储在数组第 9 个位置的结点存在兄弟结点和两个子结点,则它的兄弟结点和右子结点的位置分别是( )。
假设有一组字符 {a,b,c,d,e,f}, 对应的频率分别为 5%,9%,12%,13%,16%,45%。请问以下哪个选项是字符abcdef分别对应的一组哈夫曼编码?
用 5 个权值 10,12,15,20,25 构造哈夫曼树,该树的带权路径长度是多少?
一棵包含 1000 个结点的完全二叉树,其叶子结点的数量是多少?