c 输入n个叶子结点的权值构造哈夫曼树;根据哈夫曼树构造哈夫曼编码,以指向字符串的指针数组来存放,从叶子到根逆向求每个叶子结点的哈夫曼编码;对密文完成解码工作。
时间: 2024-05-01 08:21:28 浏览: 94
以下是C语言代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_N 1000
typedef struct _Node {
int weight;
int parent, left, right;
} Node;
void Huffman(int *w, int n, Node *tree);
void GetHuffmanCode(Node *tree, int n, char **code);
void Decode(char *msg, Node *tree, int n, char **code, char *result);
int main() {
int n;
int w[MAX_N];
Node tree[MAX_N * 2 - 1];
char *code[MAX_N];
char msg[MAX_N];
char result[MAX_N];
// 输入叶子节点权值
printf("请输入叶子节点个数n: ");
scanf("%d", &n);
printf("请输入%d个叶子节点的权值:\n", n);
for (int i = 0; i < n; i++) {
scanf("%d", &w[i]);
}
// 构造哈夫曼树
Huffman(w, n, tree);
// 构造哈夫曼编码
GetHuffmanCode(tree, n, code);
// 输入密文进行解码
printf("请输入密文: ");
scanf("%s", msg);
Decode(msg, tree, n, code, result);
// 输出解码结果
printf("解码结果为: %s\n", result);
// 释放动态分配的内存
for (int i = 0; i < n; i++) {
free(code[i]);
}
return 0;
}
// 构造哈夫曼树
void Huffman(int *w, int n, Node *tree) {
int m = n * 2 - 1;
for (int i = 0; i < m; i++) {
tree[i].weight = i < n ? w[i] : 0;
tree[i].parent = -1;
tree[i].left = -1;
tree[i].right = -1;
}
for (int i = n; i < m; i++) {
int min1 = -1, min2 = -1;
for (int j = 0; j < i; j++) {
if (tree[j].parent == -1) {
if (min1 == -1 || tree[j].weight < tree[min1].weight) {
min2 = min1;
min1 = j;
} else if (min2 == -1 || tree[j].weight < tree[min2].weight) {
min2 = j;
}
}
}
tree[i].weight = tree[min1].weight + tree[min2].weight;
tree[i].left = min1;
tree[i].right = min2;
tree[min1].parent = i;
tree[min2].parent = i;
}
}
// 构造哈夫曼编码
void GetHuffmanCode(Node *tree, int n, char **code) {
for (int i = 0; i < n; i++) {
int node = i;
int parent = tree[node].parent;
int len = 0;
code[i] = (char *) malloc(sizeof(char) * (n + 1));
while (parent != -1) {
if (tree[parent].left == node) {
code[i][len++] = '0';
} else {
code[i][len++] = '1';
}
node = parent;
parent = tree[node].parent;
}
code[i][len] = '\0';
strrev(code[i]);
}
}
// 对密文进行解码
void Decode(char *msg, Node *tree, int n, char **code, char *result) {
int p = 0;
int node = 2 * n - 2;
while (msg[p] != '\0') {
if (msg[p] == '0') {
node = tree[node].left;
} else {
node = tree[node].right;
}
if (node < n) { // 到达叶子节点
strcat(result, code[node]);
node = 2 * n - 2;
}
p++;
}
}
```
代码中使用 `Node` 结构体存储哈夫曼树的节点信息,其中 `weight` 表示节点权值,`parent` 表示父节点编号,`left` 和 `right` 分别表示左右子节点编号。`Huffman` 函数构造哈夫曼树,`GetHuffmanCode` 函数构造哈夫曼编码,`Decode` 函数对密文进行解码。
对于一个长度为 $n$ 的字符串,哈夫曼编码的长度最多为 $n \log n$,因此在代码中动态分配了长度为 $n+1$ 的字符数组来存储哈夫曼编码。在解码时,从根节点开始遍历哈夫曼树,遇到 `0` 则进入左子树,遇到 `1` 则进入右子树,直到到达叶子节点,将对应叶子节点的哈夫曼编码拼接到解码结果中,然后返回根节点继续遍历。
阅读全文