哈夫曼树
必备知识
哈夫曼树 (Huffman Tree):
1.一种用于数据压缩的二叉树,基于字符的频率构建。
2. 是基于一个加权的完全二叉树,树中的每个节点代表一个字符(或数据元素)及其频率(或权重)。
3. 核心思想是:将频率较低的元素放在树的较深位置,而将频率较高的元素放在较浅位置,这样可以实现最短的编码。
4.哈夫曼树的构建算法主要采用贪心算法
5. 每个字符的编码长度与其频率成反比,频率越高的字符,编码越短。
过程图解
(1)全部初始化为叶节点(只有根节点的树)
(2)选择字符频率最小的两个造新树
(3)删除原字符频率最小的两个节点,添加新节点(那两个节点的父节点)
(4)重复(2)(3)直到剩一个节点
例题详解
例 1 :哈夫曼树编码(易)
题目描述
哈夫曼树编码
问题描述
哈夫曼树编码
给定K个不同的字符和它们的频率,建立一棵哈夫曼树对字符进行编码,合并后的节点字符设为#。合并节点时频率小的在右边,频率相同时字符小的在右边,频率和字符都相同时,后生成的节点放右边。节点频率相同的时候优先选取节点字符值大的先进行结合。
要求按照后序遍历的顺序输出哈夫曼树中叶子节点的字符。
输入包含两部分,第一部分一个数字K表示有K个字符,第二部分有K行,每行两个数表示字符和它的频率。
样例输入
7
A 5
F 5
C 7
G 13
E 34
B 24
D 17
样例输出
E
D
G
B
F
A
C
实现思路
递归判断
AVL
由于我们针对的是 AVL 树,忘了见对应知识点–AVL
1. 设置递归终止条件
空节点:返回 true
2. 递归判断当前节点左右子树是否平衡并得到左右子树的高度
3. 计算当前节点的左右子树高度差的绝对值是否超过 1
实现代码
#include <iostream>
#include <chrono>
#include <queue>
#include <vector>
#include <unordered_map>
using namespace std;
// 哈夫曼树节点定义
struct HuffmanNode
{
char data;
int freq;
HuffmanNode *left;
HuffmanNode *right;
HuffmanNode(char data, int freq) : data(data), freq(freq), left(nullptr), right(nullptr) {
}
};
// 排序规则
struct _Compare
{
bool operator()(HuffmanNode *a, HuffmanNode *b)
{
if (a->freq == b->freq)
return a->data > b->data;
else
return a->freq > b->freq;
}
};
// 哈夫曼树类
class HuffmanTree
{
// 哈夫曼树根节点
HuffmanNode *root;
// 后序遍历输出内部方法实现
void postOrder(HuffmanNode *root, vector<char> &result)
{
if (root == nullptr)
return;
postOrder(root->left, result);
postOrder(root->right, result);
if (root->data != '~')
result.push_back(root->data);
}
// 内存清理内部方法实现
void DeleteHuffmanTree(HuffmanNode *node)
{
if (node)
{
DeleteHuffmanTree(node->left);
DeleteHuffmanTree(node->right);
delete node;
}
}
public:
HuffmanTree() : root(nullptr) {
}
~HuffmanTree() {
DeleteHuffmanTree(root); }
//建树