基础算法之Huffman编码

本文详细介绍了Huffman编码的基础知识,包括如何为字符串构建Huffman树,解析了`if (!root->left && !root->right)`的含义以及`priority_queue`的用法。通过对字符频率的统计、初始节点的创建、树的构建过程的逐步解释,展示了Huffman编码的实现原理。
摘要由CSDN通过智能技术生成
// Type your code here, or load an example.
#include<iostream>
#include<string>
#include<queue>
#include <unordered_map>
#include <vector>

using namespace std;

//树节点结构
struct Node
{
    char ch;
    int freq;
    Node *left;
    Node *right;
    Node(char ch, int freq) : ch(ch), freq(freq), left(nullptr), right(nullptr) 
    {

    };
    Node(char ch, int freq, Node* left, Node* right) : ch(ch), freq(freq), left(left), right(right) 
    {

    };


};

//比较函数,用于优先队列
struct Compare
{
    bool operator()(Node * l,Node * r)
    {
        return l->freq > r->freq;
    }
};

//遍历HUffman树,存储编码
void encode(Node * root,string str,unordered_map<char,string> &huffmanCode)
{
    if(root==nullptr)
    {
        return;

    }
    //既没有左子节点又没有右子节点
    if(!root->left && !root->right)
    {
        huffmanCode[root->ch] = str;
    }
    //二叉树分支,左边是0,右边是1
    //二叉树末端节点是编码
    encode(root->left,str+'0',huffmanCode);
    encode(root->right,str+'1',huffmanCode);
}

//构建Huffman树,并返回根节点
Node* buildHuffmanTree(string text)
{
    //将字符串中字符按照频率出现次数进行统计
    unordered_map<char, int> freq;
    for (char ch : text) {
        freq[ch]++;
    }

    //使用优先队列,构建Huffman树
    //Node* 表示元素类型
    //vector<Node*>使用底层容器,作为队列
    //比较函数对象,用于确定队列中元素的顺序
    priority_queue<Node*, vector<Node*>, Compare> pq;
    for (auto pair : freq) {
        pq.push(new Node(pair.first, pair.second));
    }

    while (pq.size() != 1) {
        Node *left = pq.top(); pq.pop();
        Node *right = pq.top(); pq.pop();
        int sum = left->freq + right->freq;
        pq.push(new Node('\0', sum, left, right));
    }

    return pq.top();
}

int main() {
    string text="AAAAABCD";
    cout << "输入一个字符串: ";
    //getline(cin, text);

    Node* root = buildHuffmanTree(text);
    unordered_map<char, string> huffmanCode;
    encode(root, "", huffmanCode);

    string strEncoded;
    for (char ch : text) {
        strEncoded += huffmanCode[ch];
    }

    cout << "ASCII编码长度: " << text.length() * 8 << " bits\n";
    cout << "Huffman编码长度: " << strEncoded.length() << " bits\n";
    cout << "压缩比: " << (text.length() * 8.0 / strEncoded.length()) << "\n";

    return 0;
}

在这里插入图片描述

1举例子

当然,我将根据提供的代码逐步解释如何为例子中的字符串 “beep boop beer!” 构建Huffman树并返回根节点。我们按照代码中的步骤来操作。

首先,我们需要统计字符串中每个字符的频率。在我们的例子中,字符频率如下:

  • ‘b’: 3
  • ‘e’: 5
  • ‘p’: 2
  • ‘o’: 2
  • ’ ': 2 (空格字符)
  • ‘r’: 1
  • ‘!’: 1

代码中的 buildHuffmanTree 函数负责构建Huffman树。下面是函数中的关键步骤:

  1. 统计频率:
    这一步通过遍历整个字符串并使用一个哈希表(unordered_map<char, int>)来计算每个字符的出现次数。

  2. 创建初始节点:
    对于每个唯一字符,我们创建一个新的 Node,包含字符(ch)和频率(freq)。这些节点被加入到优先队列(priority_queue)中,该队列使用自定义的比较函数 Compare 对节点进行排序,以确保频率最低的节点位于队列的顶部。

  3. 构建树:
    然后,我们进入一个循环,直到优先队列中只剩下一个节点为止。在每次循环中,我们执行以下操作࿱

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值