生成哈夫曼树及其编码的C语言代码:输入n个叶子结点的权值构造哈夫曼树;根据哈夫曼树构造哈夫曼编码,以指向字符串的指针数组来存放,从叶子到根逆向求每个叶子结点的哈夫曼编码;对密文完成解码工作。
时间: 2024-06-01 17:05:49 浏览: 171
以下是生成哈夫曼树及其编码的C语言代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NODE_NUM 1000
// 定义哈夫曼树结点
typedef struct huffman_node {
int weight; // 权值
int parent; // 父结点下标
int left_child; // 左子结点下标
int right_child; // 右子结点下标
} huffman_node;
// 定义哈夫曼编码结构体
typedef struct huffman_code {
char code[MAX_NODE_NUM]; // 编码
int start; // 编码起始位置
} huffman_code;
// 初始化哈夫曼树
void init_huffman_tree(huffman_node *h_tree, int n) {
for (int i = 0; i < n * 2 - 1; i++) {
h_tree[i].weight = 0;
h_tree[i].parent = -1;
h_tree[i].left_child = -1;
h_tree[i].right_child = -1;
}
}
// 构建哈夫曼树
void create_huffman_tree(huffman_node *h_tree, int *weight, int n) {
for (int i = 0; i < n; i++) {
h_tree[i].weight = weight[i];
}
for (int i = 0; i < n - 1; i++) {
// 找到权值最小的两个结点
int min1 = MAX_NODE_NUM, min2 = MAX_NODE_NUM;
int min1_idx = -1, min2_idx = -1;
for (int j = 0; j < n + i; j++) {
if (h_tree[j].parent == -1 && h_tree[j].weight < min1) {
min2 = min1;
min2_idx = min1_idx;
min1 = h_tree[j].weight;
min1_idx = j;
} else if (h_tree[j].parent == -1 && h_tree[j].weight < min2) {
min2 = h_tree[j].weight;
min2_idx = j;
}
}
// 合并权值最小的两个结点
h_tree[min1_idx].parent = n + i;
h_tree[min2_idx].parent = n + i;
h_tree[n + i].weight = h_tree[min1_idx].weight + h_tree[min2_idx].weight;
h_tree[n + i].left_child = min1_idx;
h_tree[n + i].right_child = min2_idx;
}
}
// 构建哈夫曼编码
void create_huffman_code(huffman_node *h_tree, huffman_code *h_code, int n) {
for (int i = 0; i < n; i++) {
int current_node = i;
int parent_node = h_tree[current_node].parent;
while (parent_node != -1) {
if (h_tree[parent_node].left_child == current_node) {
// 左子结点,编码为0
h_code[i].code[h_code[i].start++] = '0';
} else {
// 右子结点,编码为1
h_code[i].code[h_code[i].start++] = '1';
}
current_node = parent_node;
parent_node = h_tree[current_node].parent;
}
// 逆序存储编码
for (int j = 0; j < h_code[i].start / 2; j++) {
char temp = h_code[i].code[j];
h_code[i].code[j] = h_code[i].code[h_code[i].start - j - 1];
h_code[i].code[h_code[i].start - j - 1] = temp;
}
}
}
// 解码密文
void decode(huffman_node *h_tree, char *secret, char *plain_text, int n) {
int current_node = n * 2 - 2;
for (int i = 0; secret[i] != '\0'; i++) {
if (secret[i] == '0') {
current_node = h_tree[current_node].left_child;
} else {
current_node = h_tree[current_node].right_child;
}
if (h_tree[current_node].left_child == -1 && h_tree[current_node].right_child == -1) {
plain_text[strlen(plain_text)] = current_node + 'a';
current_node = n * 2 - 2;
}
}
}
int main() {
int n, weight[MAX_NODE_NUM];
printf("请输入叶子结点数量n:\n");
scanf("%d", &n);
printf("请输入每个叶子结点的权值:\n");
for (int i = 0; i < n; i++) {
scanf("%d", &weight[i]);
}
// 初始化哈夫曼树
huffman_node h_tree[MAX_NODE_NUM * 2 - 1];
init_huffman_tree(h_tree, n);
// 构建哈夫曼树
create_huffman_tree(h_tree, weight, n);
// 构建哈夫曼编码
huffman_code h_code[MAX_NODE_NUM];
for (int i = 0; i < n; i++) {
h_code[i].start = 0;
}
create_huffman_code(h_tree, h_code, n);
// 输出哈夫曼编码
printf("哈夫曼编码如下:\n");
for (int i = 0; i < n; i++) {
printf("%c: ", 'a' + i);
for (int j = 0; j < h_code[i].start; j++) {
printf("%c", h_code[i].code[j]);
}
printf("\n");
}
// 加密明文
char plain_text[MAX_NODE_NUM];
printf("请输入要加密的明文:\n");
scanf("%s", plain_text);
char secret[MAX_NODE_NUM * 10];
strcpy(secret, "");
for (int i = 0; plain_text[i] != '\0'; i++) {
strcat(secret, h_code[plain_text[i] - 'a'].code);
}
printf("加密后的密文为:%s\n", secret);
// 解密密文
char decrypted[MAX_NODE_NUM];
strcpy(decrypted, "");
decode(h_tree, secret, decrypted, n);
printf("解密后的明文为:%s\n", decrypted);
return 0;
}
```
阅读全文