Huffman算法

简介: Huffman算法

介绍

求解最优二叉树问题通常使用动态规划算法中的一种称为"Huffman算法"或者"Huffman编码"。

Huffman算法的基本思想:

根据节点的频率或者权重构建一棵最优二叉树。最小频率的节点会被放置在树的底部,而较大频率的节点则放置在较高的位置,以此最大限度地减少树的平均路径长度。

具体步骤如下:

1. 首先,统计所有节点的频率或者权重,并按照频率或者权重对节点进行排序。

2. 创建一个包含所有节点的森林(由单个节点组成的树)。

3. 从森林中选择两个具有最小频率或者权重的节点,并创建一个新的父节点,频率或者权重等于这两个节点的频率或者权重之和。

4. 将这两个节点作为新节点的左右子节点,并将新节点加入到森林中。

5. 重复步骤3和步骤4,直到森林中只剩下一个节点,即最优二叉树的根节点。

6. 最后,对最优二叉树进行编码,将频率或者权重较大的节点赋予较短的编码,而频率或者权重较小的节点赋予较长的编码。

Huffman算法的时间复杂度主要取决于对节点进行排序的部分,通常使用的排序算法是堆排序或者快速排序,时间复杂度为O(nlogn),其中n为节点的数量。

总结一下,Huffman算法是一种用于构建最优二叉树的动态规划算法,它通过选择频率或者权重最小的节点来构建树,以最小化树的平均路径长度。

举例

#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;
// Huffman树节点
struct HuffmanNode {
    char data;                  // 符号(字符)
    int frequency;              // 频率
    HuffmanNode* left;
    HuffmanNode* right;
    HuffmanNode(char d, int freq) : data(d), frequency(freq), left(nullptr), right(nullptr) {}
};
// 比较函数(按照频率从小到大排序)
struct Compare {
    bool operator()(const HuffmanNode* a, const HuffmanNode* b) {
        return a->frequency > b->frequency;
    }
};
// 构建Huffman树
HuffmanNode* buildHuffmanTree(const unordered_map<char, int>& freqMap) {
    // 创建小顶堆,用于选择频率最小的节点
    priority_queue<HuffmanNode*, vector<HuffmanNode*>, Compare> minHeap;
    // 创建叶子节点,并将其加入到小顶堆中
    for (const auto& entry : freqMap) {
        HuffmanNode* node = new HuffmanNode(entry.first, entry.second);
        minHeap.push(node);
    }
    // 构建Huffman树(合并节点)
    while (minHeap.size() > 1) {
        // 选择频率最小的两个节点
        HuffmanNode* leftNode = minHeap.top();
        minHeap.pop();
        HuffmanNode* rightNode = minHeap.top();
        minHeap.pop();
        // 创建新节点,频率为子节点频率之和
        HuffmanNode* newNode = new HuffmanNode('$', leftNode->frequency + rightNode->frequency);
        newNode->left = leftNode;
        newNode->right = rightNode;
        // 将新节点加入到小顶堆中
        minHeap.push(newNode);
    }
    // 返回Huffman树的根节点
    return minHeap.top();
}
// 生成Huffman编码
void generateHuffmanCodes(HuffmanNode* root, string code, unordered_map<char, string>& huffmanCodes) {
    if (root == nullptr) {
        return;
    }
    // 叶子节点表示一个字符,将其编码加入到map中
    if (root->left == nullptr && root->right == nullptr) {
        huffmanCodes[root->data] = code;
    }
    // 递归生成左子树和右子树的编码
    generateHuffmanCodes(root->left, code + "0", huffmanCodes);
    generateHuffmanCodes(root->right, code + "1", huffmanCodes);
}
// 压缩数据
string compressData(const string& data, const unordered_map<char, string>& huffmanCodes) {
    string compressedData = "";
    // 遍历原始数据,将字符替换为对应的Huffman编码
    for (char c : data) {
        compressedData += huffmanCodes.at(c);
    }
    return compressedData;
}
// 解压缩数据
string decompressData(const string& compressedData, HuffmanNode* root) {
    string decompressedData = "";
    HuffmanNode* current = root;
    // 遍历压缩后的数据,根据Huffman编码逐个恢复原始字符
    for (char c : compressedData) {
        if (c == '0') {
            current = current->left;
        } else {
            current = current->right;
        }
        // 到达叶子节点,表示找到一个字符
        if (current->left == nullptr && current->right == nullptr) {
            decompressedData += current->data;
            current = root;  // 恢复到根节点以继续下一个字符的解压缩
        }
    }
    return decompressedData;
}
int main() {
    string data = "hello huffman!";
    unordered_map<char, int> freqMap;
    // 统计字符频率
    for (char c : data) {
        freqMap[c]++;  // 字符已存在,则自增; 否则, 创建新键值对
    }
    // 构建Huffman树
    HuffmanNode* root = buildHuffmanTree(freqMap);
    // 生成Huffman编码
    unordered_map<char, string> huffmanCodes;
    generateHuffmanCodes(root, "", huffmanCodes);
    // 输出Huffman编码
    cout << "Huffman Codes:" << endl;


相关文章
基于DCT变换和huffman编码的语音压缩算法matlab仿真
基于DCT变换和huffman编码的语音压缩算法matlab仿真
|
6月前
|
存储 算法
贪心算法的高逼格应用——Huffman编码
贪心算法的高逼格应用——Huffman编码
75 8
|
7月前
|
存储 编解码 算法
基于huffman编解码的图像压缩算法matlab仿真
基于huffman编解码的图像压缩算法matlab仿真
|
Rust 算法 Kotlin
ChatGPT算法训练营—Huffman编码
Huffman 算法是一种常用于数据压缩的算法,其思想是将频繁出现的字符使用较短的编码,不频繁出现的字符使用较长的编码,以此达到压缩数据的目的。本篇文章我们就来一起学习下 Huffman 算法。
137 0
|
存储 机器学习/深度学习 算法
【算法社区】从零开始的DS生活 轻松从0基础写出Huffman树与红黑树
本文详细介绍了树的概念和术语,并配合两种树的遍历算法来进行理解。文内附有800行的详细代码实现Huffman树和红黑树,供读者理解与学习,适合点赞+收藏。有什么错误希望大家直接指出~
【算法社区】从零开始的DS生活 轻松从0基础写出Huffman树与红黑树
|
算法 Java Perl
数据结构与算法之Huffman tree(赫夫曼树 / 霍夫曼树 / 哈夫曼树 / 最优二叉树)
HuffmanTree因为翻译不同所以有其他的名字:赫夫曼树、霍夫曼树、哈夫曼树
257 0
数据结构与算法之Huffman tree(赫夫曼树 / 霍夫曼树 / 哈夫曼树 / 最优二叉树)
|
存储 人工智能 算法
【算法】赫夫曼树(Huffman)的构建和应用(编码、译码)
我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。   参考资料 《算法(java)》                           — — Robert Sedgewick, Kevin Wayne 《数据结构》                                  —...
1643 0
|
15天前
|
算法
基于WOA算法的SVDD参数寻优matlab仿真
该程序利用鲸鱼优化算法(WOA)对支持向量数据描述(SVDD)模型的参数进行优化,以提高数据分类的准确性。通过MATLAB2022A实现,展示了不同信噪比(SNR)下模型的分类误差。WOA通过模拟鲸鱼捕食行为,动态调整SVDD参数,如惩罚因子C和核函数参数γ,以寻找最优参数组合,增强模型的鲁棒性和泛化能力。
|
21天前
|
机器学习/深度学习 算法 Serverless
基于WOA-SVM的乳腺癌数据分类识别算法matlab仿真,对比BP神经网络和SVM
本项目利用鲸鱼优化算法(WOA)优化支持向量机(SVM)参数,针对乳腺癌早期诊断问题,通过MATLAB 2022a实现。核心代码包括参数初始化、目标函数计算、位置更新等步骤,并附有详细中文注释及操作视频。实验结果显示,WOA-SVM在提高分类精度和泛化能力方面表现出色,为乳腺癌的早期诊断提供了有效的技术支持。
|
1天前
|
供应链 算法 调度
排队算法的matlab仿真,带GUI界面
该程序使用MATLAB 2022A版本实现排队算法的仿真,并带有GUI界面。程序支持单队列单服务台、单队列多服务台和多队列多服务台三种排队方式。核心函数`func_mms2`通过模拟到达时间和服务时间,计算阻塞率和利用率。排队论研究系统中顾客和服务台的交互行为,广泛应用于通信网络、生产调度和服务行业等领域,旨在优化系统性能,减少等待时间,提高资源利用率。
下一篇
DataWorks