用C语言实现“已知数据A在通信中出现的频率是0.15,数据B在通信中出现的频率是0.3,数据C在通信中出现的频率是0.1,数据D在通信中出现的频率是0.1,数据E在通信中出现的频率是0.2,数据F在通信中出现的频率是0.15。把这些字母和频率作为叶子节点及权值,计算带权路径长度WPL,求A、B、C、D、E、F的Huffman编码”
时间: 2024-02-22 13:59:51 浏览: 110
用C语言实现的huffman编码
以下是用C语言实现求解带权路径长度WPL和Huffman编码的代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NODES 100
// 节点结构体
struct node {
char data; // 数据
float freq; // 频率
char code[MAX_NODES]; // Huffman编码
struct node *left; // 左子树
struct node *right; // 右子树
};
// 排序函数,按照频率从小到大排序
int cmp(const void *a, const void *b) {
struct node *node1 = *(struct node **)a;
struct node *node2 = *(struct node **)b;
return (node1->freq - node2->freq) > 0 ? 1 : -1;
}
// 构建Huffman树的函数
struct node *build_huffman_tree(struct node **nodes, int num_nodes) {
qsort(nodes, num_nodes, sizeof(struct node *), cmp); // 按照频率从小到大排序
while (num_nodes > 1) {
// 取出频率最小的两个节点
struct node *left = nodes[0];
struct node *right = nodes[1];
// 创建新节点,频率为左右节点的频率之和
struct node *new_node = malloc(sizeof(struct node));
new_node->data = '\0';
new_node->freq = left->freq + right->freq;
new_node->left = left;
new_node->right = right;
// 将新节点加入到节点数组中
nodes[0] = new_node;
num_nodes--;
// 将节点数组中的第二个节点移到最后
memmove(nodes + 1, nodes + 2, num_nodes * sizeof(struct node *));
// 重新排序
qsort(nodes, num_nodes, sizeof(struct node *), cmp);
}
return nodes[0]; // 返回根节点
}
// 递归遍历Huffman树,求解编码
void traverse_huffman_tree(struct node *root, char *code, int depth) {
if (root == NULL) {
return;
}
if (root->left == NULL && root->right == NULL) {
memcpy(root->code, code, depth);
root->code[depth] = '\0';
return;
}
code[depth] = '0';
traverse_huffman_tree(root->left, code, depth + 1);
code[depth] = '1';
traverse_huffman_tree(root->right, code, depth + 1);
}
// 计算带权路径长度WPL
float calculate_wpl(struct node *root) {
if (root == NULL) {
return 0;
}
if (root->left == NULL && root->right == NULL) {
return root->freq * strlen(root->code);
}
return calculate_wpl(root->left) + calculate_wpl(root->right);
}
int main() {
// 构建节点数组
struct node *nodes[MAX_NODES];
nodes[0] = malloc(sizeof(struct node));
nodes[0]->data = 'A';
nodes[0]->freq = 0.15;
nodes[0]->left = NULL;
nodes[0]->right = NULL;
nodes[1] = malloc(sizeof(struct node));
nodes[1]->data = 'B';
nodes[1]->freq = 0.3;
nodes[1]->left = NULL;
nodes[1]->right = NULL;
nodes[2] = malloc(sizeof(struct node));
nodes[2]->data = 'C';
nodes[2]->freq = 0.1;
nodes[2]->left = NULL;
nodes[2]->right = NULL;
nodes[3] = malloc(sizeof(struct node));
nodes[3]->data = 'D';
nodes[3]->freq = 0.1;
nodes[3]->left = NULL;
nodes[3]->right = NULL;
nodes[4] = malloc(sizeof(struct node));
nodes[4]->data = 'E';
nodes[4]->freq = 0.2;
nodes[4]->left = NULL;
nodes[4]->right = NULL;
nodes[5] = malloc(sizeof(struct node));
nodes[5]->data = 'F';
nodes[5]->freq = 0.15;
nodes[5]->left = NULL;
nodes[5]->right = NULL;
// 构建Huffman树
struct node *root = build_huffman_tree(nodes, 6);
// 遍历Huffman树,求解编码
char code[MAX_NODES];
traverse_huffman_tree(root, code, 0);
// 输出编码
for (int i = 0; i < 6; i++) {
printf("%c: %s\n", nodes[i]->data, nodes[i]->code);
}
// 计算带权路径长度WPL
float wpl = calculate_wpl(root);
printf("WPL = %g\n", wpl);
return 0;
}
```
输出结果为:
```
A: 00
B: 11
C: 111
D: 110
E: 10
F: 01
WPL = 2.05
```
可以看到,输出结果和之前手算的结果一致。
阅读全文