// 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
对节点进行排序,以确保频率最低的节点位于队列的顶部。 -
构建树:
然后,我们进入一个循环,直到优先队列中只剩下一个节点为止。在每次循环中,我们执行以下操作:<