c++哈弗曼树编码译码
时间: 2023-12-27 12:00:55 浏览: 49
哈夫曼树编码是一种通过构建最优前缀编码树来实现数据压缩的方法。首先,我们需要统计待编码的字符出现的频率,并根据频率构建哈夫曼树。在哈弗曼树中,出现频率越高的字符,其在树中的位置越靠近根节点。
在进行编码时,我们从哈弗曼树的根节点开始,沿着路径向下,对于左子树走向的路径标记为0,右子树走向的路径标记为1,直到叶子节点。这样,我们就可以得到每个字符对应的哈弗曼编码。
在解码时,我们同样从哈弗曼树的根节点开始,根据编码的0和1分别向左或向右移动,直到叶子节点,得到对应的字符。
通过哈弗曼编码,我们可以用较短的编码表示出现频率高的字符,从而实现了数据的压缩。同时,哈弗曼编码是无损压缩,即可以完全还原原始数据,因为每个字符对应的编码都是唯一的。
哈弗曼编码是一种非常有效的压缩技术,在数据传输、存储和通信等领域都有广泛的应用。通过构建哈弗曼树,对数据进行编码和译码,可以大大提高数据的压缩效率,减少存储空间和传输带宽的消耗。
相关问题
哈弗曼编码和译码C++
以下是哈夫曼编码和译码的C++代码示例:
```cpp
#include <iostream>
#include <queue>
#include <map>
#include <string>
using namespace std;
// 哈夫曼树节点结构体
struct HuffmanNode {
char ch; // 字符
int freq; // 出现频率
HuffmanNode *left, *right; // 左右子节点
HuffmanNode(char c, int f) : ch(c), freq(f), left(NULL), right(NULL) {}
// 重载小于号,用于优先队列排序
bool operator<(const HuffmanNode& n) const {
return freq > n.freq; // 按出现频率从小到大排序
}
};
// 构建哈夫曼树
HuffmanNode* buildHuffmanTree(const string& text) {
// 统计字符出现频率
map<char, int> freqMap;
for (char ch : text) {
freqMap[ch]++;
}
// 构建优先队列,按出现频率从小到大排序
priority_queue<HuffmanNode> pq;
for (auto it = freqMap.begin(); it != freqMap.end(); ++it) {
pq.push(HuffmanNode(it->first, it->second));
}
// 构建哈夫曼树
while (pq.size() > 1) {
HuffmanNode* left = new HuffmanNode(pq.top().ch, pq.top().freq);
pq.pop();
HuffmanNode* right = new HuffmanNode(pq.top().ch, pq.top().freq);
pq.pop();
HuffmanNode* parent = new HuffmanNode('\0', left->freq + right->freq);
parent->left = left;
parent->right = right;
pq.push(*parent);
}
return new HuffmanNode('\0', pq.top().freq);
}
// 递归编码
void encodeHelper(HuffmanNode* root, string code, map<char, string>& codeMap) {
if (!root) {
return;
}
if (root->left == NULL && root->right == NULL) { // 叶子节点
codeMap[root->ch] = code;
}
encodeHelper(root->left, code + "0", codeMap);
encodeHelper(root->right, code + "1", codeMap);
}
// 哈夫曼编码
map<char, string> huffmanEncode(const string& text) {
map<char, string> codeMap;
HuffmanNode* root = buildHuffmanTree(text);
encodeHelper(root, "", codeMap);
return codeMap;
}
// 哈夫曼译码
string huffmanDecode(const string& text, HuffmanNode* root) {
string result;
HuffmanNode* p = root;
for (char ch : text) {
if (ch == '0') {
p = p->left;
} else {
p = p->right;
}
if (p->left == NULL && p->right == NULL) { // 叶子节点
result += p->ch;
p = root; // 重置为根节点
}
}
return result;
}
int main() {
string text = "hello world";
cout << "原文:" << text << endl;
// 哈夫曼编码
map<char, string> codeMap = huffmanEncode(text);
cout << "编码表:" << endl;
for (auto it = codeMap.begin(); it != codeMap.end(); ++it) {
cout << it->first << ":" << it->second << endl;
}
string encodedText;
for (char ch : text) {
encodedText += codeMap[ch];
}
cout << "编码结果:" << encodedText << endl;
// 哈夫曼译码
HuffmanNode* root = buildHuffmanTree(text);
string decodedText = huffmanDecode(encodedText, root);
cout << "译码结果:" << decodedText << endl;
// 释放内存
delete root;
return 0;
}
```
输出结果:
```
原文:hello world
编码表:
:110
d:1110
e:10
h:0110
l:00
o:0111
r:1111
w:01101
编码结果:0110011000101110000010111110111011101110
译码结果:hello world
```
根据哈弗曼树求哈夫曼编码
根据哈夫曼树求哈夫曼编码的步骤如下:
1. 从哈夫曼树的根节点开始,向左走为0,向右走为1,直到叶子节点,记录下路径上的0和1,得到该叶子节点的哈夫曼编码。
2. 对于哈夫曼树中的每个叶子节点,都按照上述方法求出其哈夫曼编码。
3. 将所有叶子节点的哈夫曼编码组成的序列作为哈夫曼编码表。
下面是一个示例,假设有如下的哈夫曼树:
```
5
/ \
2 3
/ \ / \
1 1 1 2
```
按照上述步骤求出每个叶子节点的哈夫曼编码:
- 对于叶子节点1,从根节点向左走得到0,记录下来,得到哈夫曼编码为0。
- 对于叶子节点2,从根节点向右走得到1,然后再向左走得到0,记录下来,得到哈夫曼编码为10。
- 对于叶子节点3,从根节点向右走得到1,然后再向右走得到1,记录下来,得到哈夫曼编码为11。
因此,该哈夫曼树的哈夫曼编码表为:
```
1: 0
2: 10
3: 11
```