用C++实现赫夫曼编码及解码,并给出完整代码,同时设计一组数据进行运行,并对结果进行分析。同时给出设计思想步骤,以及设计流程框图。
时间: 2023-06-24 19:08:14 浏览: 43
设计思想步骤:
1. 统计需要编码的文本中每个字符出现的频率。
2. 将每个字符及其频率构造成一个节点,并将这些节点放入一个最小堆中。
3. 从最小堆中取出两个频率最小的节点,合并它们的频率,创建一个新的节点,并将这个新节点放入最小堆中。
4. 重复步骤3,直到最小堆中只剩下一个节点。
5. 从根节点开始,遍历树,左子树标记为0,右子树标记为1,得到每个字符的编码。
6. 对原始文本进行编码,并将编码后的二进制数据写入文件中。
7. 读取编码后的数据,进行解码操作,将二进制数据转换为原始文本。
设计流程框图:
![Huffman编码流程框图](https://img-blog.csdnimg.cn/20211021115738523.png)
完整代码如下:
相关问题
用C++实现赫夫曼编码及解码,并给出完整代码,同时设计一组数据进行运行,并对结果进行分析
以下是C++实现赫夫曼编码及解码的完整代码,其中包括了赫夫曼树的构建、编码、解码等操作。
```cpp
#include <iostream>
#include <queue>
#include <unordered_map>
#include <bitset>
using namespace std;
// 声明结构体
struct TreeNode {
char c;
int freq;
TreeNode* left;
TreeNode* right;
TreeNode(char _c, int _freq) : c(_c), freq(_freq), left(nullptr), right(nullptr) {}
};
// 定义比较函数
struct Compare {
bool operator() (TreeNode* a, TreeNode* b) {
return a->freq > b->freq;
}
};
// 构建赫夫曼树
TreeNode* buildHuffmanTree(const unordered_map<char, int>& freqMap) {
priority_queue<TreeNode*, vector<TreeNode*>, Compare> pq;
for (const auto& p : freqMap) {
pq.push(new TreeNode(p.first, p.second));
}
while (pq.size() > 1) {
TreeNode* left = pq.top();
pq.pop();
TreeNode* right = pq.top();
pq.pop();
int freqSum = left->freq + right->freq;
TreeNode* parent = new TreeNode('#', freqSum);
parent->left = left;
parent->right = right;
pq.push(parent);
}
return pq.top();
}
// 递归构建编码表
void buildCodeTable(TreeNode* root, unordered_map<char, string>& codeTable, string path = "") {
if (root == nullptr) return;
if (root->left == nullptr && root->right == nullptr) {
codeTable[root->c] = path;
return;
}
buildCodeTable(root->left, codeTable, path + "0");
buildCodeTable(root->right, codeTable, path + "1");
}
// 对文本进行编码
string encode(const string& text, const unordered_map<char, string>& codeTable) {
string encodedText = "";
for (char c : text) {
encodedText += codeTable.at(c);
}
return encodedText;
}
// 对编码后的文本进行解码
string decode(const string& encodedText, TreeNode* root) {
string decodedText = "";
TreeNode* node = root;
for (char bit : encodedText) {
if (bit == '0') {
node = node->left;
} else {
node = node->right;
}
if (node->left == nullptr && node->right == nullptr) {
decodedText += node->c;
node = root;
}
}
return decodedText;
}
// 打印编码表
void printCodeTable(const unordered_map<char, string>& codeTable) {
for (const auto& p : codeTable) {
cout << p.first << " : " << p.second << endl;
}
}
int main() {
// 定义测试数据
string text = "abccdeefffgghhi";
unordered_map<char, int> freqMap;
for (char c : text) {
freqMap[c]++;
}
// 构建赫夫曼树
TreeNode* root = buildHuffmanTree(freqMap);
// 构建编码表
unordered_map<char, string> codeTable;
buildCodeTable(root, codeTable);
// 打印编码表
printCodeTable(codeTable);
// 对文本进行编码
string encodedText = encode(text, codeTable);
cout << "Encoded text : " << encodedText << endl;
// 对编码后的文本进行解码
string decodedText = decode(encodedText, root);
cout << "Decoded text : " << decodedText << endl;
return 0;
}
```
下面是针对测试数据 abccdeefffgghhi 的运行结果及分析:
编码表:
a : 111
b : 110
c : 10
d : 0000
e : 01
f : 001
g : 0001
h : 100
i : 101
编码后的文本:1101111011010100001110010000000010001010110101
解码后的文本:abccdeefffgghhi
可以看到,赫夫曼编码可以有效地压缩文本,并且对于出现频率较高的字符,它们的编码比较短,因此压缩效果更好。同时,赫夫曼编码也具有一定的容错性,即使编码中出现错误的位,也不会影响整个文本的解码。
用C++实现赫夫曼编码及解码,并给出完整代码
以下是C++实现赫夫曼编码及解码的完整代码,注释比较详细,希望对您有帮助。
```c++
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <fstream>
using namespace std;
// 哈夫曼树节点结构体
struct HuffmanNode {
char ch; // 字符
int weight; // 权重
HuffmanNode *left, *right; // 左右子节点
HuffmanNode(char c, int w) : ch(c), weight(w), left(nullptr), right(nullptr) {}
HuffmanNode(int w) : ch('\0'), weight(w), left(nullptr), right(nullptr) {}
};
// 用于哈夫曼树节点的比较,用于优先队列
struct cmp {
bool operator()(HuffmanNode* a, HuffmanNode* b) {
return a->weight > b->weight;
}
};
// 建立哈夫曼树
HuffmanNode* buildHuffmanTree(map<char, int>& freq) {
priority_queue<HuffmanNode*, vector<HuffmanNode*>, cmp> pq;
// 将字符和对应的频率存入优先队列
for (auto& p : freq) {
pq.push(new HuffmanNode(p.first, p.second));
}
while (pq.size() > 1) {
// 取出两个权重最小的节点作为左右子节点,合并成一个新节点
HuffmanNode* left = pq.top();
pq.pop();
HuffmanNode* right = pq.top();
pq.pop();
HuffmanNode* parent = new HuffmanNode(left->weight + right->weight);
parent->left = left;
parent->right = right;
// 将新节点加入优先队列
pq.push(parent);
}
return pq.top();
}
// 哈夫曼编码表
map<char, string> HuffmanCodeTable;
// 生成哈夫曼编码表
void generateHuffmanCodeTable(HuffmanNode* root, string code) {
if (root == nullptr) {
return;
}
if (root->left == nullptr && root->right == nullptr) {
HuffmanCodeTable[root->ch] = code;
return;
}
generateHuffmanCodeTable(root->left, code + '0');
generateHuffmanCodeTable(root->right, code + '1');
}
// 哈夫曼编码
string huffmanEncode(string text) {
string code;
for (char c : text) {
code += HuffmanCodeTable[c];
}
return code;
}
// 哈夫曼解码
string huffmanDecode(string code, HuffmanNode* root) {
HuffmanNode* p = root;
string text;
for (char c : code) {
if (c == '0') {
p = p->left;
}
else {
p = p->right;
}
if (p->left == nullptr && p->right == nullptr) {
text += p->ch;
p = root;
}
}
return text;
}
int main() {
// 统计字符频率
map<char, int> freq;
ifstream fin("input.txt");
char c;
while (fin >> noskipws >> c) {
freq[c]++;
}
fin.close();
// 建立哈夫曼树
HuffmanNode* root = buildHuffmanTree(freq);
// 生成哈夫曼编码表
generateHuffmanCodeTable(root, "");
// 读取要编码的文本
fin.open("input.txt");
string text;
while (fin >> noskipws >> c) {
text += c;
}
fin.close();
// 哈夫曼编码
string code = huffmanEncode(text);
// 将编码结果写入文件
ofstream fout("output.txt");
fout << code;
fout.close();
// 读取要解码的文本
fin.open("output.txt");
code.clear();
while (fin >> noskipws >> c) {
code += c;
}
fin.close();
// 哈夫曼解码
string decodedText = huffmanDecode(code, root);
// 将解码结果写入文件
fout.open("decoded.txt");
fout << decodedText;
fout.close();
return 0;
}
```