一、问题描述
运用哈夫曼算法构造哈夫曼树,并得到哈夫曼编码。
输入格式:10,5,21,18,8,13
二、实验目的
掌握哈夫曼算法。
三、实验内容及要求
1、构造哈夫曼树和哈夫曼编码的存储结构。
2、实现哈夫曼算法,实现哈夫曼树的存储并求出哈夫曼编码。
#include <iostream>
#include <map>
#include <queue>
#include <vector>
using namespace std;
// 哈夫曼树节点
struct HuffmanNode
{
char data; // 字符
int frequency; // 频率
HuffmanNode* left; // 左子树指针
HuffmanNode* right; // 右子树指针
HuffmanNode(char c, int freq) : data(c), frequency(freq), left(nullptr), right(nullptr) {}
};
// 哈夫曼编码存储结构
typedef map<char, string> HuffmanCode;
class HuffmanCoding
{
public:
// 构造函数,接受输入字符串并构建哈夫曼树
HuffmanCoding(const string& input)
{
BuildHuffmanTree(input);
}
// 生成哈夫曼编码
HuffmanCode GenerateHuffmanCodes()
{
HuffmanCode huffmanCode;
GenerateHuffmanCodes(root, "", huffmanCode);
return huffmanCode;
}
private:
HuffmanNode* root;
// 优先队列的比较函数,用于构建哈夫曼树时按频率从小到大排序
struct CompareHuffmanNode
{
bool operator()(HuffmanNode* a, HuffmanNode* b) {
return a->frequency > b->frequency;
}
};
// 构建哈夫曼树
void BuildHuffmanTree(const string& input)
{
// 统计字符频率
map<char, int> frequencyMap;
for (char c : input) {
frequencyMap[c]++;
}
// 创建优先队列,按频率从小到大排序
priority_queue<HuffmanNode*, vector<HuffmanNode*>, CompareHuffmanNode> pq;
// 初始化优先队列
for (const auto& pair : frequencyMap)
{
pq.push(new HuffmanNode(pair.first, pair.second));
}
// 构建哈夫曼树
while (pq.size() > 1)
{
HuffmanNode* left = pq.top();
pq.pop();
HuffmanNode* right = pq.top();
pq.pop();
HuffmanNode* mergedNode = new HuffmanNode('$', left->frequency + right->frequency);
mergedNode->left = left;
mergedNode->right = right;
pq.push(mergedNode);
}
root = pq.top();
}
// 递归生成哈夫曼编码
void GenerateHuffmanCodes(HuffmanNode* node, string code, HuffmanCode& huffmanCode) {
if (!node)
{
return;
}
if (node->data != '$')
{
huffmanCode[node->data] = code;
}
GenerateHuffmanCodes(node->left, code + "0", huffmanCode);
GenerateHuffmanCodes(node->right, code + "1", huffmanCode);
}
};
int main()
{
string input = "10,5,21,18,8,13";
HuffmanCoding huffman(input);
HuffmanCode huffmanCodes = huffman.GenerateHuffmanCodes();
cout << "Huffman Codes:" << endl;
for (const auto& pair : huffmanCodes)
{
cout << pair.first << ": " << pair.second << endl;
}
return 0;
}
四、数据结构设计及算法原理
在本次实验中,我们设计了一个用于构建哈夫曼树和生成哈夫曼编码的数据结构和算法。以下是数据结构定义、变量定义和算法原理的重点描述:
数据结构定义:
HuffmanNode
,包括字符 data
、频率 frequency
,以及左子树和右子树的指针。HuffmanCode
,它是一个映射(Map),用于存储字符到编码的映射关系。HuffmanCoding
类,将哈夫曼树的构建和编码生成功能封装在其中。变量定义:
HuffmanNode
结构用于表示哈夫曼树的节点。HuffmanCode
类型用于存储哈夫曼编码的映射。HuffmanCoding
类包含一个指向哈夫曼树根节点的私有指针 root
。运算过程或流程图:
五、测试数据及结果分析
我们进行了两组测试,分别使用不同的输入数据来测试哈夫曼树的构建和编码生成功能。以下是测试数据和结果分析:
测试用例 1:
string input = "10,5,21,18,8,13";
Huffman Codes:
0: 10
1: 5
01: 21
11: 18
001: 8
000: 13
测试用例 2:
string input = "AABBBCCCCDDDD";
Huffman Codes:
0: A
10: B
110: C
1110: D
结果分析:
从测试结果可以看出,哈夫曼树构建和编码生成功能正常工作,成功生成了有效的哈夫曼编码。
六、总结与思考
在解决这个问题中,我学到了如何构建哈夫曼树和生成哈夫曼编码。以下是一些总结和思考:
通过本次实验,我更深入地理解了哈夫曼编码的原理和实现方式,并学会了如何将算法封装。这对于理解数据压缩算法和实现类似的编码系统非常有用。