// 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树。下面是函数中的关键步骤:
-
统计频率:
这一步通过遍历整个字符串并使用一个哈希表(unordered_map<char, int>
)来计算每个字符的出现次数。 -
创建初始节点:
对于每个唯一字符,我们创建一个新的Node
,包含字符(ch
)和频率(freq
)。这些节点被加入到优先队列(priority_queue
)中,该队列使用自定义的比较函数Compare
对节点进行排序,以确保频率最低的节点位于队列的顶部。 -
构建树:
然后,我们进入一个循环,直到优先队列中只剩下一个节点为止。在每次循环中,我们执行以下操作:<