c语言请编程实现哈夫曼树的构造,以及对该赫夫曼树的编码。
时间: 2024-05-07 11:19:12 浏览: 16
下面是哈夫曼树的构造和编码的C语言实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHAR_NUM 256 // 字符集大小
#define MAX_CODE_LEN 100 // 编码串最大长度
// 哈夫曼树节点结构体
typedef struct huffman_node {
int weight; // 权重
int parent; // 父节点下标
int lchild; // 左子节点下标
int rchild; // 右子节点下标
} huffman_node;
// 哈夫曼编码结构体
typedef struct huffman_code {
char ch; // 字符
char code[MAX_CODE_LEN + 1]; // 编码串
} huffman_code;
// 选择两个权值最小的节点
void select_min(huffman_node *nodes, int n, int *p1, int *p2) {
int i, min1, min2;
min1 = min2 = -1;
for (i = 0; i < n; i++) {
if (nodes[i].parent == -1) { // 未被选择
if (min1 == -1 || nodes[i].weight < nodes[min1].weight) {
min2 = min1; // 更新次小值
min1 = i; // 更新最小值
} else if (min2 == -1 || nodes[i].weight < nodes[min2].weight) {
min2 = i; // 更新次小值
}
}
}
*p1 = min1;
*p2 = min2;
}
// 构造哈夫曼树
void create_huffman_tree(huffman_node *nodes, int n) {
int i, p1, p2;
for (i = 0; i < 2 * n - 1; i++) {
nodes[i].parent = nodes[i].lchild = nodes[i].rchild = -1;
}
for (i = n; i < 2 * n - 1; i++) {
select_min(nodes, i, &p1, &p2);
nodes[p1].parent = nodes[p2].parent = i;
nodes[i].lchild = p1;
nodes[i].rchild = p2;
nodes[i].weight = nodes[p1].weight + nodes[p2].weight;
}
}
// 递归求哈夫曼编码
void get_huffman_code(huffman_node *nodes, int i, huffman_code *codes, int depth, char *code) {
if (nodes[i].lchild == -1 && nodes[i].rchild == -1) { // 叶子节点
code[depth] = '\0';
strcpy(codes[i - MAX_CHAR_NUM].code, code);
return;
}
code[depth] = '0'; // 左子树编码为0
get_huffman_code(nodes, nodes[i].lchild, codes, depth + 1, code);
code[depth] = '1'; // 右子树编码为1
get_huffman_code(nodes, nodes[i].rchild, codes, depth + 1, code);
}
// 哈夫曼编码
void huffman_encoding(huffman_code *codes, char *str) {
int i, j;
huffman_node nodes[2 * MAX_CHAR_NUM - 1];
int n = strlen(str);
for (i = 0; i < MAX_CHAR_NUM; i++) {
nodes[i].weight = 0;
nodes[i].parent = nodes[i].lchild = nodes[i].rchild = -1;
}
for (i = 0; i < n; i++) {
nodes[str[i]].weight++;
}
create_huffman_tree(nodes, MAX_CHAR_NUM);
char code[MAX_CODE_LEN + 1];
get_huffman_code(nodes, 2 * MAX_CHAR_NUM - 2, codes, 0, code);
}
// 测试
int main() {
char str[] = "Hello, world!";
huffman_code codes[MAX_CHAR_NUM];
int i;
for (i = 0; i < MAX_CHAR_NUM; i++) {
codes[i].ch = i;
codes[i].code[0] = '\0';
}
huffman_encoding(codes, str);
for (i = 0; i < MAX_CHAR_NUM; i++) {
if (codes[i].code[0] != '\0') {
printf("%c: %s\n", codes[i].ch, codes[i].code);
}
}
return 0;
}
```
代码中使用了两个结构体 `huffman_node` 和 `huffman_code`,其中 `huffman_node` 表示哈夫曼树节点,包含权重、父节点下标、左子节点下标和右子节点下标四个成员变量;`huffman_code` 表示哈夫曼编码,包含字符和编码串两个成员变量。`MAX_CHAR_NUM` 宏定义为字符集大小,`MAX_CODE_LEN` 宏定义为编码串最大长度。
程序首先定义了两个函数 `select_min` 和 `create_huffman_tree`,分别用于选择两个权值最小的节点和构造哈夫曼树。然后定义了递归函数 `get_huffman_code`,用于递归求哈夫曼编码。最后定义了函数 `huffman_encoding`,用于对字符串进行哈夫曼编码。
在 `main` 函数中,我们测试了对字符串 "Hello, world!" 进行哈夫曼编码的结果。代码输出了所有字符的哈夫曼编码。