哈夫曼压缩与解压缩c++
时间: 2023-10-17 18:05:09 浏览: 55
哈夫曼压缩和解压缩是一种基于哈夫曼树的数据压缩算法,它通过对数据中出现频率较高的字符使用较短的编码,从而实现对数据的压缩。以下是C++代码实现:
压缩:
```c++
#include <iostream>
#include <queue>
#include <unordered_map>
#include <vector>
using namespace std;
// 定义哈夫曼树结点
struct HuffmanNode {
char ch; // 字符
int freq; // 字符出现频率
HuffmanNode* left;
HuffmanNode* right;
HuffmanNode(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {}
};
// 比较函数,用于构建最小堆
struct Compare {
bool operator()(HuffmanNode* a, HuffmanNode* b) {
return a->freq > b->freq;
}
};
// 构建哈夫曼树
HuffmanNode* buildHuffmanTree(string str) {
unordered_map<char, int> freqMap; // 统计字符出现频率
for (char c : str) {
freqMap[c]++;
}
priority_queue<HuffmanNode*, vector<HuffmanNode*>, Compare> minHeap; // 最小堆
// 将每个字符及其频率存入最小堆中
for (auto p : freqMap) {
minHeap.push(new HuffmanNode(p.first, p.second));
}
// 构建哈夫曼树
while (minHeap.size() > 1) {
HuffmanNode* left = minHeap.top();
minHeap.pop();
HuffmanNode* right = minHeap.top();
minHeap.pop();
// 合并结点
HuffmanNode* parent = new HuffmanNode('$', left->freq + right->freq);
parent->left = left;
parent->right = right;
minHeap.push(parent);
}
return minHeap.top(); // 返回根结点
}
// 将哈夫曼树编码存入哈希表中
void encode(HuffmanNode* root, string code, unordered_map<char, string>& map) {
if (!root) {
return;
}
if (root->left == nullptr && root->right == nullptr) { // 叶结点
map[root->ch] = code;
return;
}
encode(root->left, code + "0", map);
encode(root->right, code + "1", map);
}
// 压缩函数
string compress(string str) {
string compressed = "";
if (str.empty()) {
return compressed;
}
HuffmanNode* root = buildHuffmanTree(str); // 构建哈夫曼树
unordered_map<char, string> map; // 存储字符编码
encode(root, "", map); // 构建哈夫曼编码表
// 将编码后的字符串存入compressed中
for (char c : str) {
compressed += map[c];
}
return compressed;
}
int main() {
string str = "hello world";
string compressed = compress(str);
cout << "Compressed string: " << compressed << endl;
return 0;
}
```
解压缩:
```c++
#include <iostream>
#include <unordered_map>
using namespace std;
// 定义哈夫曼树结点
struct HuffmanNode {
char ch; // 字符
int freq; // 字符出现频率
HuffmanNode* left;
HuffmanNode* right;
HuffmanNode(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {}
};
// 解码函数
string decode(string compressed, HuffmanNode* root) {
string decompressed = "";
if (compressed.empty()) {
return decompressed;
}
HuffmanNode* curr = root;
// 遍历编码后的字符串,解码
for (char c : compressed) {
if (c == '0') {
curr = curr->left;
} else {
curr = curr->right;
}
if (curr->left == nullptr && curr->right == nullptr) { // 叶结点
decompressed += curr->ch;
curr = root;
}
}
return decompressed;
}
int main() {
string compressed = "01010110101100110011011111000101110010101";
unordered_map<char, string> map = {{'h', "0"}, {'e', "10"}, {'l', "110"}, {'o', "111"}, {' ', "01"}, {'w', "001"}, {'r', "0001"}, {'d', "00001"}};
HuffmanNode* root = new HuffmanNode('$', 0);
for (auto p : map) {
string code = p.second;
HuffmanNode* curr = root;
for (char c : code) {
if (c == '0') {
if (curr->left == nullptr) {
curr->left = new HuffmanNode('$', 0);
}
curr = curr->left;
} else {
if (curr->right == nullptr) {
curr->right = new HuffmanNode('$', 0);
}
curr = curr->right;
}
}
curr->ch = p.first;
}
string decompressed = decode(compressed, root);
cout << "Decompressed string: " << decompressed << endl;
return 0;
}
```