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;


相关文章
|
8月前
|
算法
基于DCT变换和huffman编码的语音压缩算法matlab仿真
基于DCT变换和huffman编码的语音压缩算法matlab仿真
|
3月前
|
存储 编解码 算法
基于huffman编解码的图像压缩算法matlab仿真
基于huffman编解码的图像压缩算法matlab仿真
|
2月前
|
机器学习/深度学习 算法
m基于深度学习的64QAM调制解调系统频偏估计和补偿算法matlab仿真
### 算法仿真结果 展示5张图像,描绘了基于深度学习的频偏估计和补偿在MATLAB 2022a中的仿真效果。 ### 理论概要 - 深度学习算法用于建立信号与频偏的非线性映射,无需导频,节省资源。 - 网络模型(如CNN或RNN)处理IQ数据,提取特征,简化估计补偿过程,降低复杂度。 - 64QAM系统中,通过神经网络实现精确频偏感知,增强通信性能。 ### MATLAB核心程序 - 代码生成64QAM信号,模拟不同SNR和频偏条件,使用深度学习进行相位估计和补偿。 - 仿真比较了有无补偿的误码率,显示补偿能显著改善通信质量。 ```
33 1
|
10天前
|
机器学习/深度学习 人工智能 算法
基于DCT和扩频的音频水印嵌入提取算法matlab仿真
本文介绍了结合DCT和扩频技术的音频水印算法,用于在不降低音质的情况下嵌入版权信息。在matlab2022a中实现,算法利用DCT进行频域处理,通过扩频增强水印的隐蔽性和抗攻击性。核心程序展示了水印的嵌入与提取过程,包括DCT变换、水印扩频及反变换步骤。该方法有效且专业,未来研究将侧重于提高实用性和安全性。
|
25天前
|
机器学习/深度学习 算法
【MATLAB】GA_BP神经网络时序预测算法
【MATLAB】GA_BP神经网络时序预测算法
35 8
|
1月前
|
机器学习/深度学习 算法 Serverless
【MATLAB】PSO_BP神经网络回归预测算法(适用光伏发电回归预测等)
【MATLAB】PSO_BP神经网络回归预测算法(适用光伏发电回归预测等)
30 1
|
1天前
|
算法 数据安全/隐私保护 计算机视觉
基于DCT变换的彩色图像双重水印嵌入和提取算法matlab仿真
**算法摘要:** - 图形展示:展示灰度与彩色图像水印应用,主辅水印嵌入。 - 软件环境:MATLAB 2022a。 - 算法原理:双重水印,转换至YCbCr/YIQ,仅影响亮度;图像分割为M×N块,DCT变换后嵌入水印。 - 流程概览:两步水印嵌入,每步对应不同图示表示。 - 核心代码未提供。
|
1天前
|
机器学习/深度学习 算法 数据可视化
Matlab决策树、模糊C-均值聚类算法分析高校教师职称学历评分可视化
Matlab决策树、模糊C-均值聚类算法分析高校教师职称学历评分可视化
|
1天前
|
算法 TensorFlow 算法框架/工具
基于直方图的图像阈值计算和分割算法FPGA实现,包含tb测试文件和MATLAB辅助验证
这是一个关于图像处理的算法实现摘要,主要包括四部分:展示了四张算法运行的效果图;提到了使用的软件版本为VIVADO 2019.2和matlab 2022a;介绍了算法理论,即基于直方图的图像阈值分割,通过灰度直方图分布选取阈值来区分图像区域;并提供了部分Verilog代码,该代码读取图像数据,进行处理,并输出结果到&quot;result.txt&quot;以供MATLAB显示图像分割效果。
|
2天前
|
算法 搜索推荐 数据挖掘
MATLAB模糊C均值聚类FCM改进的推荐系统协同过滤算法分析MovieLens电影数据集
MATLAB模糊C均值聚类FCM改进的推荐系统协同过滤算法分析MovieLens电影数据集