用C语言结构体定义邻接矩阵表示图的结构体,并写出解决下列问题的程序,已知数据六个字母及在通信中出现频率如下表: A B C D E F 0.15 0.3 0.1 0.1 0.2 0.15 把这些字母和频率作为叶子结点及权值,完成如下工作。 (1) 画出对应的Huffman树。 (2) 计算带权路径长度WPL(要有过程)。 (3) 求A、B、C、D、E、F的Huffman编码。
时间: 2024-02-22 17:59:41 浏览: 84
好的,接下来回答第二个问题:
根据Huffman编码的算法,我们可以得到以下步骤:
1. 将这六个字母及它们的频率分别作为叶子节点和权值构建一颗森林,每个节点的权值为该节点下所有叶子节点的权值之和。
2. 从森林中选出两个根节点权值最小的树作为左右子树,构建一颗新的树,其根节点权值为左右子树的权值之和。
3. 将新的树加入到森林中。
4. 重复步骤 2 和步骤 3,直到森林中只剩下一颗树,即为 Huffman 树。
下面是具体实现的代码:
```c
#include <stdio.h>
#include <stdlib.h>
#define MAX_LEAF_NUM 6
typedef struct {
char ch;
float weight;
int parent;
int left_child;
int right_child;
} HNode;
typedef struct {
HNode nodes[MAX_LEAF_NUM * 2 - 1];
int leaf_num;
} HTree;
void init_tree(HTree *tree, float weights[]) {
int i;
for (i = 0; i < MAX_LEAF_NUM; i++) {
tree->nodes[i].ch = 'A' + i;
tree->nodes[i].weight = weights[i];
tree->nodes[i].parent = -1;
tree->nodes[i].left_child = -1;
tree->nodes[i].right_child = -1;
}
tree->leaf_num = MAX_LEAF_NUM;
}
void select_small(HNode *nodes, int n, int *s1, int *s2) {
int i, j;
for (i = 0; i < n; i++) {
if (nodes[i].parent == -1) {
*s1 = i;
break;
}
}
for (j = i + 1; j < n; j++) {
if (nodes[j].parent == -1 && nodes[j].weight < nodes[*s1].weight) {
*s1 = j;
}
}
for (i = 0; i < n; i++) {
if (nodes[i].parent == -1 && i != *s1) {
*s2 = i;
break;
}
}
for (j = i + 1; j < n; j++) {
if (nodes[j].parent == -1 && j != *s1 && nodes[j].weight < nodes[*s2].weight) {
*s2 = j;
}
}
}
void create_huffman_tree(HTree *tree) {
int i, s1, s2;
for (i = tree->leaf_num; i < tree->leaf_num * 2 - 1; i++) {
select_small(tree->nodes, i, &s1, &s2);
tree->nodes[i].weight = tree->nodes[s1].weight + tree->nodes[s2].weight;
tree->nodes[i].left_child = s1;
tree->nodes[i].right_child = s2;
tree->nodes[s1].parent = i;
tree->nodes[s2].parent = i;
}
}
void calc_wpl(HTree *tree, float *wpl) {
int i, j;
for (i = 0; i < tree->leaf_num; i++) {
j = i;
while (tree->nodes[j].parent != -1) {
if (j == tree->nodes[tree->nodes[j].parent].left_child) {
*wpl += tree->nodes[tree->nodes[j].parent].weight;
}
j = tree->nodes[j].parent;
}
}
}
void get_huffman_code(HTree *tree, char ch, char *code) {
int i, j, k;
for (i = 0; i < tree->leaf_num; i++) {
if (tree->nodes[i].ch == ch) {
j = i;
break;
}
}
k = tree->leaf_num - 1;
while (tree->nodes[j].parent != -1) {
if (j == tree->nodes[tree->nodes[j].parent].left_child) {
code[--k] = '0';
} else {
code[--k] = '1';
}
j = tree->nodes[j].parent;
}
}
int main() {
float weights[MAX_LEAF_NUM] = {0.15, 0.3, 0.1, 0.1, 0.2, 0.15};
HTree tree;
init_tree(&tree, weights);
create_huffman_tree(&tree);
float wpl = 0;
calc_wpl(&tree, &wpl);
printf("带权路径长度WPL为:%.2f\n", wpl);
char code[MAX_LEAF_NUM];
int i;
for (i = 0; i < MAX_LEAF_NUM; i++) {
get_huffman_code(&tree, 'A' + i, code);
printf("%c的Huffman编码为:%s\n", 'A' + i, code);
}
return 0;
}
```
以上代码中,我们定义了两个结构体,`HNode` 表示 Huffman 树的节点,`HTree` 表示整个 Huffman 树。
在 `init_tree` 函数中,我们初始化了叶子节点。
在 `select_small` 函数中,我们找到森林中权值最小的两个节点。
在 `create_huffman_tree` 函数中,我们根据找到的两个节点构建一颗新的树,并将其加入到森林中。
在 `calc_wpl` 函数中,我们计算带权路径长度 WPL。
在 `get_huffman_code` 函数中,我们根据给定的字母找到对应的节点,并根据该节点的父节点和左右子节点的关系得到 Huffman 编码。
最后,在 `main` 函数中,我们调用上述函数,并输出结果。
阅读全文