哈夫曼树

哈夫曼树(Huffman Tree)是一种最优的二叉树,常用于数据压缩,如在 Huffman 编码中使用。它是根据字符出现的频率来构造的,频率越高的字符越靠近树的根,频率低的字符则在较深的节点上。其核心思想是通过构建一颗最小堆(或者优先队列)来逐步合并最小的两个节点,直到所有节点都合并成一颗哈夫曼树。

哈夫曼树的构建过程:

  1. 统计频率:首先统计每个字符出现的频率。
  2. 构建最小堆:将每个字符作为一个树的节点插入一个最小堆(优先队列)中。
  3. 合并最小频率的节点:每次从最小堆中取出两个频率最小的节点,创建一个新节点,其频率为这两个节点频率之和。然后将这个新节点插入回最小堆。
  4. 重复步骤3,直到堆中只剩下一个节点,这个节点就是哈夫曼树的根节点
cpp 复制代码
#include <iostream>
#include <queue>
#include <vector>
#include <unordered_map>
#include <string>

using namespace std;

// 哈夫曼树的节点
struct HuffmanNode {
    char ch;              // 存储字符
    int freq;             // 字符的频率
    HuffmanNode* left;    // 左子树
    HuffmanNode* right;   // 右子树

    // 构造函数
    HuffmanNode(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {}

    // 定义优先级队列的比较规则:按频率最小的优先
    struct Compare {
        bool operator()(HuffmanNode* l, HuffmanNode* r) {
            return l->freq > r->freq; // 返回 true 时 l 排在 r 后面
        }
    };
};

// 用递归生成哈夫曼编码
void generateHuffmanCodes(HuffmanNode* root, const string& str, unordered_map<char, string>& huffmanCode) {
    if (root == nullptr)
        return;

    // 如果是叶子节点,保存它的编码
    if (!root->left && !root->right) {
        huffmanCode[root->ch] = str;
    }

    // 遍历左子树和右子树
    generateHuffmanCodes(root->left, str + "0", huffmanCode);
    generateHuffmanCodes(root->right, str + "1", huffmanCode);
}

// 构造哈夫曼树
HuffmanNode* buildHuffmanTree(const unordered_map<char, int>& freq) {
    // 优先队列(最小堆)用于按频率排序
    priority_queue<HuffmanNode*, vector<HuffmanNode*>, HuffmanNode::Compare> minHeap;

    // 创建叶子节点并插入最小堆
    for (const auto& pair : freq) {
        minHeap.push(new HuffmanNode(pair.first, pair.second));
    }

    // 合并节点直到只剩一个节点
    while (minHeap.size() > 1) {
        // 取出两个最小的节点
        HuffmanNode* left = minHeap.top(); minHeap.pop();
        HuffmanNode* right = minHeap.top(); minHeap.pop();

        // 创建一个新的内部节点,频率为左右节点频率之和
        HuffmanNode* node = new HuffmanNode('\0', left->freq + right->freq);
        node->left = left;
        node->right = right;

        // 将新节点插入最小堆
        minHeap.push(node);
    }

    // 最后堆中剩下的节点就是哈夫曼树的根节点
    return minHeap.top();
}

// 打印哈夫曼编码
void printHuffmanCodes(const unordered_map<char, string>& huffmanCode) {
    for (const auto& pair : huffmanCode) {
        cout << pair.first << ": " << pair.second << endl;
    }
}

int main() {
    // 输入字符串
    string text = "this is an example for huffman encoding";

    // 统计每个字符的频率
    unordered_map<char, int> freq;
    for (char c : text) {
        freq[c]++;
    }

    // 构建哈夫曼树
    HuffmanNode* root = buildHuffmanTree(freq);

    // 保存每个字符的哈夫曼编码
    unordered_map<char, string> huffmanCode;

    // 生成哈夫曼编码
    generateHuffmanCodes(root, "", huffmanCode);

    // 打印哈夫曼编码
    printHuffmanCodes(huffmanCode);

    return 0;
}
相关推荐
野渡拾光1 小时前
【考研408数据结构-05】 串与KMP算法:模式匹配的艺术
数据结构·考研·算法
tainshuai3 小时前
用 KNN 算法解锁分类的奥秘:从电影类型到鸢尾花开
算法·分类·数据挖掘
Coovally AI模型快速验证9 小时前
农田扫描提速37%!基于检测置信度的无人机“智能抽查”路径规划,Coovally一键加速模型落地
深度学习·算法·yolo·计算机视觉·transformer·无人机
pusue_the_sun9 小时前
数据结构:二叉树oj练习
c语言·数据结构·算法·二叉树
RaymondZhao3410 小时前
【全面推导】策略梯度算法:公式、偏差方差与进化
人工智能·深度学习·算法·机器学习·chatgpt
zhangfeng113310 小时前
DBSCAN算法详解和参数优化,基于密度的空间聚类算法,特别擅长处理不规则形状的聚类和噪声数据
算法·机器学习·聚类
啊阿狸不会拉杆11 小时前
《算法导论》第 32 章 - 字符串匹配
开发语言·c++·算法
小学生的信奥之路11 小时前
洛谷P3817题解:贪心算法解决糖果分配问题
c++·算法·贪心算法
你知道网上冲浪吗12 小时前
【原创理论】Stochastic Coupled Dyadic System (SCDS):一个用于两性关系动力学建模的随机耦合系统框架
python·算法·数学建模·数值分析
地平线开发者13 小时前
征程 6 | PTQ 精度调优辅助代码,总有你用得上的
算法·自动驾驶