输入n个叶子结点的权值构造哈夫曼树;根据哈夫曼树构造哈夫曼编码,以指向字符串的指针数组来存放,从叶子到根逆向求每个叶子结点的哈夫曼编码;对密文完成解码工作。用c语言实现
时间: 2023-06-29 11:03:51 浏览: 157
以下是使用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; // 右子结点下标
} HuffmanNode;
// 哈夫曼编码的结构体定义
typedef struct huffman_code {
int bit[MAX_NODE_NUM]; // 存储每个叶子结点的哈夫曼编码
int start; // 编码在数组中的起始位置
} HuffmanCode;
// 构造哈夫曼树
void buildHuffmanTree(HuffmanNode *huffman_tree, int n) {
int i, j;
int min1, min2;
// 初始化哈夫曼树
for (i = 0; i < 2 * n - 1; i++) {
huffman_tree[i].parent = -1; // 置空
huffman_tree[i].left_child = -1;
huffman_tree[i].right_child = -1;
}
// 输入叶子结点的权值
for (i = 0; i < n; i++) {
printf("请输入第%d个叶子结点的权值:", i + 1);
scanf("%d", &huffman_tree[i].weight);
}
// 构造哈夫曼树
for (i = 0; i < n - 1; i++) {
min1 = min2 = MAX_NODE_NUM;
int node1, node2;
// 在所有未加入哈夫曼树的结点中,找到权值最小的两个结点
for (j = 0; j < n + i; j++) {
if (huffman_tree[j].parent == -1) {
if (huffman_tree[j].weight < min1) {
min2 = min1;
node2 = node1;
min1 = huffman_tree[j].weight;
node1 = j;
} else if (huffman_tree[j].weight < min2) {
min2 = huffman_tree[j].weight;
node2 = j;
}
}
}
// 将找到的两个结点合并为一棵子树,加入哈夫曼树中
huffman_tree[node1].parent = n + i;
huffman_tree[node2].parent = n + i;
huffman_tree[n + i].left_child = node1;
huffman_tree[n + i].right_child = node2;
huffman_tree[n + i].weight = min1 + min2;
}
}
// 从叶子到根逆向求每个叶子结点的哈夫曼编码
void getHuffmanCode(HuffmanNode *huffman_tree, HuffmanCode *huffman_code, int n) {
int i, j, parent, current;
for (i = 0; i < n; i++) {
huffman_code[i].start = n - 1; // 初始化起始位置
current = i; // 当前结点
parent = huffman_tree[current].parent; // 父结点
// 从叶子到根逆向求每个叶子结点的哈夫曼编码
while (parent != -1) {
if (huffman_tree[parent].left_child == current) {
huffman_code[i].bit[huffman_code[i].start] = 0;
} else {
huffman_code[i].bit[huffman_code[i].start] = 1;
}
huffman_code[i].start--;
current = parent;
parent = huffman_tree[current].parent;
}
huffman_code[i].start++; // 修正起始位置
}
}
// 对明文进行编码
void encode(char *plaintext, HuffmanCode *huffman_code, int n, char *ciphertext) {
int i, j, len, index;
len = strlen(plaintext);
index = 0;
// 将明文编码为密文
for (i = 0; i < len; i++) {
for (j = 0; j < n; j++) {
if (plaintext[i] == j + 'A') {
memcpy(ciphertext + index, huffman_code[j].bit + huffman_code[j].start, (n - huffman_code[j].start) * sizeof(int));
index += n - huffman_code[j].start;
}
}
}
ciphertext[index] = '\0'; // 加上字符串结束符
}
// 对密文进行解码
void decode(char *ciphertext, HuffmanNode *huffman_tree, int n, char *plaintext) {
int i, index, current;
index = 0;
current = 2 * n - 2; // 从哈夫曼树的根结点开始
while (ciphertext[index] != '\0') {
if (ciphertext[index] == '0') {
current = huffman_tree[current].left_child;
} else {
current = huffman_tree[current].right_child;
}
if (huffman_tree[current].left_child == -1 && huffman_tree[current].right_child == -1) { // 叶子结点
plaintext[strlen(plaintext)] = current - n + 'A'; // 将叶子结点的值转化为字符
current = 2 * n - 2; // 回到哈夫曼树的根结点
}
index++;
}
plaintext[strlen(plaintext)] = '\0'; // 加上字符串结束符
}
int main() {
int n, i;
char plaintext[MAX_NODE_NUM], ciphertext[MAX_NODE_NUM], decoded_plaintext[MAX_NODE_NUM];
HuffmanNode huffman_tree[MAX_NODE_NUM];
HuffmanCode huffman_code[MAX_NODE_NUM];
printf("请输入叶子结点的个数:");
scanf("%d", &n);
buildHuffmanTree(huffman_tree, n);
getHuffmanCode(huffman_tree, huffman_code, n);
printf("请输入要加密的明文:");
scanf("%s", plaintext);
encode(plaintext, huffman_code, n, ciphertext);
printf("密文为:%s\n", ciphertext);
decode(ciphertext, huffman_tree, n, decoded_plaintext);
printf("解密后的明文为:%s\n", decoded_plaintext);
return 0;
}
```
注意:在构造哈夫曼树时,我们使用了两个数组来表示哈夫曼树的结构,一个是 `HuffmanNode` 数组,用于存储哈夫曼树的每个结点的权值、父节点下标、左子结点下标和右子结点下标;另一个是 `HuffmanCode` 数组,用于存储每个叶子结点的哈夫曼编码。
在具体实现中,我们使用了一个 `buildHuffmanTree` 函数来构造哈夫曼树;一个 `getHuffmanCode` 函数从叶子到根逆向求每个叶子结点的哈夫曼编码;一个 `encode` 函数将明文编码为密文;一个 `decode` 函数将密文解码为明文。
在输入叶子结点的权值时,我们假设这些权值是从 `A` 到 `A+n-1` 的,即第 `i` 个叶子结点的权值为 `i`。
最后,我们在 `main` 函数中完成对上述函数的调用,并输出加密后的密文和解密后的明文。
阅读全文