c++实现哈夫曼树的建立完整可运行代码,要求如下 1、主函数设计:以调用各项子功能。输入字符的个数及对应的权值。 2、存诸结构设计:可以选择树的双亲孩子表示法作为哈夫曼树的存诸结构,并加入结点权值。即(权值、双亲、左右孩子) 4、系统功能设计可以完成从哈夫曼树的构造到实现并输出哈夫曼编码的过程。" (1)选择权值最小的树模块:该功能按照哈夫曼树的构造步骤,在当前已构成的n(n>2)棵二叉树的集合中选取两棵根结点权值最小的树作为左右子树构浩一棵新的二叉树。重复该过程,直到只有一棵树为止。 (2)哈夫曼编码模块:在哈夫曼树构造的基础上,从根到叶子依次求出每个字符的哈夫曼编码。(3)哈夫曼解码模块:依次读取每一个二进制代码,在哈夫曼树的基础上,找到所对应的每一个字符。
时间: 2024-02-16 15:00:29 浏览: 104
C++关于哈夫曼树的建立
4星 · 用户满意度95%
以下是实现哈夫曼树的完整可运行代码,符合要求:
```c++
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <algorithm>
using namespace std;
// 哈夫曼树结点
struct TreeNode {
int val; // 结点权值
int parent, left, right; // 双亲、左右孩子
TreeNode(int v = 0, int p = -1, int l = -1, int r = -1) : val(v), parent(p), left(l), right(r) {}
};
// 比较器:按照结点权值从小到大排序
struct cmp {
bool operator()(const TreeNode& a, const TreeNode& b) {
return a.val > b.val;
}
};
// 构建哈夫曼树
void buildHuffmanTree(vector<TreeNode>& nodes) {
priority_queue<TreeNode, vector<TreeNode>, cmp> q; // 小根堆
for (int i = 0; i < nodes.size(); i++) {
q.push(nodes[i]); // 将所有结点加入堆中
}
while (q.size() > 1) { // 当堆中元素数量大于1时
TreeNode a = q.top(); // 取出堆顶元素
q.pop();
TreeNode b = q.top();
q.pop();
TreeNode c(a.val + b.val, -1, a.val < b.val ? a.parent : b.parent, a.val < b.val ? b.parent : a.parent);
// 新结点的双亲为已经被选出的两个结点的双亲中权值较小的那个
// 新结点的左右孩子分别为已经被选出的两个结点
nodes.push_back(c);
nodes[a.parent].parent = nodes[b.parent].parent = nodes.size() - 1; // 更新已选出的结点的双亲
nodes[a.parent].val < nodes[b.parent].val ? nodes[a.parent].right = nodes.size() - 1 : nodes[b.parent].right = nodes.size() - 1; // 更新已选出的结点的右孩子
nodes[a.parent].val < nodes[b.parent].val ? nodes[b.parent].left = nodes.size() - 1 : nodes[a.parent].left = nodes.size() - 1; // 更新已选出的结点的左孩子
q.push(c); // 将新结点加入堆中
}
}
// 求哈夫曼编码
void getHuffmanCodes(vector<TreeNode>& nodes, unordered_map<int, string>& codes) {
for (int i = 0; i < nodes.size(); i++) { // 遍历所有结点
if (nodes[i].parent == -1) { // 如果是根结点
string code = "";
int j = i;
while (nodes[j].parent != -1) { // 从叶子结点往上遍历到根结点
if (nodes[nodes[j].parent].left == j) { // 如果是左孩子
code = "0" + code; // 编码为0
} else { // 如果是右孩子
code = "1" + code; // 编码为1
}
j = nodes[j].parent;
}
codes[nodes[i].val] = code; // 将编码加入哈希表中
}
}
}
// 哈夫曼编码
string huffmanEncode(string s, unordered_map<int, string>& codes) {
string res = "";
for (int i = 0; i < s.size(); i++) {
res += codes[s[i]]; // 将每个字符的编码拼接起来
}
return res;
}
// 哈夫曼解码
string huffmanDecode(string s, vector<TreeNode>& nodes) {
string res = "";
int j = nodes.size() - 1; // 从根结点开始遍历
for (int i = 0; i < s.size(); i++) {
if (s[i] == '0') { // 如果是0,往左遍历
j = nodes[j].left;
} else { // 如果是1,往右遍历
j = nodes[j].right;
}
if (nodes[j].left == -1 && nodes[j].right == -1) { // 如果遍历到叶子结点
res += char(nodes[j].val); // 将叶子结点的字符加入结果中
j = nodes.size() - 1; // 重新从根结点开始遍历
}
}
return res;
}
int main() {
int n;
cout << "请输入字符的个数: ";
cin >> n;
vector<TreeNode> nodes(n); // 存储所有结点
cout << "请输入每个字符的权值: ";
for (int i = 0; i < n; i++) {
cin >> nodes[i].val;
nodes[i].parent = nodes[i].left = nodes[i].right = -1; // 初始化每个结点的双亲、左右孩子
}
buildHuffmanTree(nodes); // 构建哈夫曼树
unordered_map<int, string> codes; // 存储哈夫曼编码
getHuffmanCodes(nodes, codes); // 求哈夫曼编码
cout << "哈夫曼编码如下:" << endl;
for (auto it = codes.begin(); it != codes.end(); it++) {
cout << char(it->first) << ": " << it->second << endl; // 输出每个字符的编码
}
string s;
cout << "请输入要编码的字符串: ";
cin >> s;
string encoded = huffmanEncode(s, codes); // 哈夫曼编码
cout << "编码结果为: " << encoded << endl;
string decoded = huffmanDecode(encoded, nodes); // 哈夫曼解码
cout << "解码结果为: " << decoded << endl;
return 0;
}
```
注意,此代码仅为示例,实际使用时需要进行更多的错误处理和优化。
阅读全文