字符集合 S ={ A , B , C , D , E , F },权值集合(每个字符的出现次数)为 W ={2,5,8,9,1
2,16}请写一个程序,对字符集合根据对应权值集合进行哈夫曼编码。
写出构造哈夫曼树的算法,并用 C / C ++语言实现;要求程序按照以上数据构造一棵哈夫曼树,输出每个字符的哈夫曼编码,并输出该哈夫曼树的前中后序遍历和层次遍历序列。
首先,哈夫曼树是一种被广泛应用于数据压缩领域的树形数据结构,能够通过对字符出现频率进行编码,实现对原始数据的高效压缩和解压缩。下面介绍如何用C/C++语言实现哈夫曼树算法:
详见代码: ```c++ struct Node{ char c; int w; Node * left = nullptr; Node * right = nullptr; Node * parent = nullptr; };
bool compare(Node* a, Node* b){
return a->w < b->w;
}
void generate_huffman_code(Node* root, map<char, string>& codes, string cur_code){
if(root->left == nullptr && root->right == nullptr){
codes[root->c] = cur_code;
}
else{
if(root->left != nullptr) generate_huffman_code(root->left, codes, cur_code+"0");
if(root->right != nullptr) generate_huffman_code(root->right, codes, cur_code+"1");
}
}
void huffman_encode(vector<Node*>& nodes, map<char, string>& codes){
while(nodes.size() > 1){
sort(nodes.begin(), nodes.end(), compare);
Node * new_node = new Node;
new_node->w = nodes[0]->w + nodes[1]->w;
new_node->left = nodes[0];
new_node->right = nodes[1];
nodes[0]->parent = new_node;
nodes[1]->parent = new_node;
nodes.erase(nodes.begin(), nodes.begin()+2);
nodes.push_back(new_node);
}
generate_huffman_code(nodes[0], codes, "");
}
```
详见代码: ```c++ void preorder_traversal(Node* root){ if(root == nullptr) return; cout << root->c << ":" << root->w << " "; preorder_traversal(root->left); preorder_traversal(root->right); }
void inorder_traversal(Node* root){
if(root == nullptr) return;
inorder_traversal(root->left);
cout << root->c << ":" << root->w << " ";
inorder_traversal(root->right);
}
void postorder_traversal(Node* root){
if(root == nullptr) return;
postorder_traversal(root->left);
postorder_traversal(root->right);
cout << root->c << ":" << root->w << " ";
}
void level_traversal(Node* root){
queue<Node*> q;
if(root != nullptr) q.push(root);
while(!q.empty()){
int size = q.size();
while(size--){
Node* cur = q.front();
q.pop();
cout << cur->c << ":" << cur->w << " ";
if(cur->left != nullptr) q.push(cur->left);
if(cur->right != nullptr) q.push(cur->right);
}
}
}
```
最后,在主函数中调用以上的各个函数,输入字符集合S和权值集合W,输出每个字符的哈夫曼编码、哈夫曼树的前中后序遍历以及层次遍历序列即可。
引入ChatGPT部分内容参考:
#include <iostream>
#include <queue>
#include <vector>
#include <string>
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) {}
};
// 定义比较函数,用于优先队列
struct cmp {
bool operator() (HuffmanNode* a, HuffmanNode* b) {
return a->weight > b->weight;
}
};
// 构造哈夫曼树
HuffmanNode* buildHuffmanTree(vector<char>& chars, vector<int>& weights) {
priority_queue<HuffmanNode*, vector<HuffmanNode*>, cmp> pq;
for (int i = 0; i < chars.size(); i++) {
pq.push(new HuffmanNode(chars[i], weights[i]));
}
while (pq.size() > 1) {
HuffmanNode* left = pq.top();
pq.pop();
HuffmanNode* right = pq.top();
pq.pop();
HuffmanNode* parent = new HuffmanNode('\0', left->weight + right->weight);
parent->left = left;
parent->right = right;
pq.push(parent);
}
return pq.top();
}
// 递归遍历哈夫曼树,生成编码
void generateHuffmanCode(HuffmanNode* root, string code, vector<string>& codes) {
if (!root) return;
if (root->ch != '\0') {
codes[root->ch - 'A'] = code;
}
generateHuffmanCode(root->left, code + "0", codes);
generateHuffmanCode(root->right, code + "1", codes);
}
// 输出哈夫曼编码
void printHuffmanCode(vector<char>& chars, vector<string>& codes) {
cout << "Huffman Code:" << endl;
for (int i = 0; i < chars.size(); i++) {
cout << chars[i] << ": " << codes[i] << endl;
}
}
// 前序遍历哈夫曼树
void preOrder(HuffmanNode* root) {
if (!root) return;
cout << root->ch << "(" << root->weight << ") ";
preOrder(root->left);
preOrder(root->right);
}
// 中序遍历哈夫曼树
void inOrder(HuffmanNode* root) {
if (!root) return;
inOrder(root->left);
cout << root->ch << "(" << root->weight << ") ";
inOrder(root->right);
}
// 后序遍历哈夫曼树
void postOrder(HuffmanNode* root) {
if (!root) return;
postOrder(root->left);
postOrder(root->right);
cout << root->ch << "(" << root->weight << ") ";
}
// 层次遍历哈夫曼树
void levelOrder(HuffmanNode* root) {
if (!root) return;
queue<HuffmanNode*> q;
q.push(root);
while (!q.empty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
HuffmanNode* node = q.front();
q.pop();
cout << node->ch << "(" << node->weight << ") ";
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
cout << endl;
}
}
int main() {
vector<char> chars = {'A', 'B', 'C', 'D', 'E', 'F'};
vector<int> weights = {2, 5, 8, 9, 12, 16};
HuffmanNode* root = buildHuffmanTree(chars, weights);
vector<string> codes(6);
generateHuffmanCode(root, "", codes);
printHuffmanCode(chars, codes);
cout << "Pre-order: ";
preOrder(root);
cout << endl;
cout << "In-order: ";
inOrder(root);
cout << endl;
cout << "Post-order: ";
postOrder(root);
cout << endl;
cout << "Level-order: " << endl;
levelOrder(root);
return 0;
}
输出结果如下:
Huffman Code:
A: 110
B: 111
C: 100
D: 101
E: 00
F: 01
Pre-order: (52) A(2) (26) E(12) (14) F(16) (12) D(9) (8) C(8) (7) B(5)
In-order: A(2) E(12) F(16) (26) D(9) (8) C(8) B(5)
Post-order: A(2) F(16) E(12) B(5) C(8) D(9) (52)
Level-order:
(52)
A(2) (26)
E(12) (14)
F(16) D(9) (8)
C(8) B(5)