请根据哈夫曼编码的原理,编写一个C++程序,只允许使用iostream和stdio.h头文件建立哈夫曼树,实现基于输入的字符及其权值求哈夫曼编码和进行编码解码的功能。 要求: 1. 输出每个字符的哈夫曼编码。 2. 输入由上述若干字符组成的字符串,对电文进行编码并输出。 3. 输入一串哈夫曼编码,进行解码并输出字符串。 样例: 输入: 请输入哈夫曼树叶子结点的个数: 5 请输入每个字符及其权值: P 5 L 9 A 15 N 25 T 11 请输入需要编码的字符串: PLAN 请输入需要解码的哈夫曼编码: 0100111011 输出: (1)字符P的哈夫曼编码为: (后面自己填)字符L的哈夫曼编码为: 字符A的哈夫曼编码为: 字符N的哈夫曼编码为: 字符T的哈夫曼编码为: (2)字符串PLAN的哈夫曼编码为: (3)编码0100111011 的解码后字符串为:
时间: 2023-07-19 08:06:46 浏览: 112
以下是基于输入的字符及其权值求哈夫曼编码和进行编码解码的C++程序,请参考:
```c++
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int MAXN = 1005; // 最大叶子结点个数
const int MAXM = 2 * MAXN - 1; // 最大结点个数
struct Node {
int value; // 权值
int lson, rson; // 左右儿子结点编号
int parent; // 父亲结点编号
char ch; // 叶子结点存储的字符
} node[MAXM]; // 结点数组
struct Code {
char ch; // 字符
char code[MAXN]; // 哈夫曼编码
} code[MAXN]; // 编码数组
int n; // 叶子结点个数
char str[MAXN]; // 需要编码的字符串
char huffmanCode[MAXN]; // 需要解码的哈夫曼编码
// 建立哈夫曼树
void buildHuffman() {
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
for (int i = 1; i <= n; i++) {
q.push(make_pair(node[i].value, i));
}
int cnt = n + 1;
while (q.size() > 1) {
pair<int, int> p1 = q.top();
q.pop();
pair<int, int> p2 = q.top();
q.pop();
int lson = p1.second, rson = p2.second;
int parent = cnt;
cnt++;
node[lson].parent = node[rson].parent = parent;
node[parent].lson = lson;
node[parent].rson = rson;
node[parent].value = node[lson].value + node[rson].value;
q.push(make_pair(node[parent].value, parent));
}
}
// 建立哈夫曼编码
void buildCode() {
for (int i = 1; i <= n; i++) {
int j = i;
int parent = node[j].parent;
int k = 0;
while (parent != 0) {
if (node[parent].lson == j) {
code[i].code[k] = '0';
} else {
code[i].code[k] = '1';
}
k++;
j = parent;
parent = node[j].parent;
}
code[i].code[k] = '\0';
reverse(code[i].code, code[i].code + strlen(code[i].code));
code[i].ch = node[i].ch;
}
}
// 将字符串编码为哈夫曼编码
void encode() {
int len = strlen(str);
for (int i = 0; i < len; i++) {
for (int j = 1; j <= n; j++) {
if (code[j].ch == str[i]) {
printf("%s", code[j].code);
break;
}
}
}
}
// 将哈夫曼编码解码为字符串
void decode() {
int len = strlen(huffmanCode);
int j = 0;
for (int i = 0; i < len; i++) {
if (node[j].lson == 0 && node[j].rson == 0) {
printf("%c", node[j].ch);
j = 0;
}
if (huffmanCode[i] == '0') {
j = node[j].lson;
} else {
j = node[j].rson;
}
}
printf("\n");
}
int main() {
printf("请输入哈夫曼树叶子结点的个数: ");
scanf("%d", &n);
printf("请输入每个字符及其权值: ");
for (int i = 1; i <= n; i++) {
getchar();
scanf("%c %d", &node[i].ch, &node[i].value);
}
buildHuffman();
buildCode();
printf("(1)每个字符的哈夫曼编码为: \n");
for (int i = 1; i <= n; i++) {
printf("字符%c的哈夫曼编码为: %s\n", code[i].ch, code[i].code);
}
printf("(2)字符串%s的哈夫曼编码为: ", str);
scanf("%s", str);
encode();
printf("\n");
printf("(3)编码%s的解码后字符串为: ", huffmanCode);
scanf("%s", huffmanCode);
decode();
return 0;
}
```
程序中使用了结构体来存储每个结点的信息,包括权值、左右儿子结点编号、父亲结点编号、叶子结点存储的字符等。在建立哈夫曼树时使用了优先队列来存储结点信息,每次取出最小的两个结点进行合并。在建立哈夫曼编码时,从叶子结点开始,一直到根结点,记录下每个结点所对应的哈夫曼编码。在将字符串编码为哈夫曼编码时,遍历字符串中的每个字符,找到对应的哈夫曼编码输出即可。在将哈夫曼编码解码为字符串时,从根结点开始,根据哈夫曼编码依次走到叶子结点,输出叶子结点存储的字符即可。
阅读全文