输入n个叶子结点的权值构造哈夫曼树;根据哈夫曼树构造哈夫曼编码,以指向字符串的指针数组来存放,从叶子到跟逆向求每个叶子结点的哈夫曼编码;对密文完成解码工作。用C语言来实现
时间: 2023-06-29 11:15:43 浏览: 103
根据给定的n个权值构造哈夫曼树。通过遍历此二叉树完成哈夫曼编码。
4星 · 用户满意度95%
好的,我会根据您的要求为您解答这个问题。
以下是C语言的实现代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NODE 100
typedef struct TreeNode {
int weight; // 权值
int parent; // 父节点
int lchild, rchild; // 左右孩子节点
} TreeNode, *HuffmanTree;
// 选择权值最小的两个节点
void select(HuffmanTree HT, int n, int *s1, int *s2)
{
int i;
int min1 = MAX_NODE, min2 = MAX_NODE; // 初始化为一个较大的数,确保初始值比所有节点的权值都大
for (i = 1; i <= n; i++) {
if (HT[i].parent == 0) { // 没有父节点的节点才能作为选择的对象
if (HT[i].weight < min1) {
min2 = min1;
*s2 = *s1;
min1 = HT[i].weight;
*s1 = i;
} else if (HT[i].weight < min2) {
min2 = HT[i].weight;
*s2 = i;
}
}
}
}
// 构建哈夫曼树
void createHuffmanTree(HuffmanTree *HT, int *w, int n)
{
int m = 2 * n - 1;
int i, s1, s2;
*HT = (HuffmanTree)malloc((m + 1) * sizeof(TreeNode));
for (i = 1; i <= n; i++) { // 初始化叶子节点
(*HT)[i].weight = w[i];
(*HT)[i].parent = 0;
(*HT)[i].lchild = 0;
(*HT)[i].rchild = 0;
}
for (; i <= m; i++) { // 初始化非叶子节点
(*HT)[i].weight = 0;
(*HT)[i].parent = 0;
(*HT)[i].lchild = 0;
(*HT)[i].rchild = 0;
}
for (i = n + 1; i <= m; i++) {
select(*HT, i - 1, &s1, &s2); // 选择权值最小的两个节点
(*HT)[s1].parent = i;
(*HT)[s2].parent = i;
(*HT)[i].lchild = s1;
(*HT)[i].rchild = s2;
(*HT)[i].weight = (*HT)[s1].weight + (*HT)[s2].weight;
}
}
// 哈夫曼编码
void huffmanEncoding(HuffmanTree HT, char **HC, int n)
{
int i, c, p;
char *temp = (char *)malloc(n * sizeof(char)); // 临时存放编码
for (i = 1; i <= n; i++) { // 处理每个叶子节点
c = i;
p = HT[c].parent;
int k = 0;
while (p) { // 从叶子节点向上直到根节点
if (HT[p].lchild == c) { // 如果是左孩子节点,则编码为0
temp[k++] = '0';
} else { // 如果是右孩子节点,则编码为1
temp[k++] = '1';
}
c = p;
p = HT[c].parent;
}
// 反转编码
temp[k] = '\0';
int len = strlen(temp);
HC[i] = (char *)malloc((len + 1) * sizeof(char));
for (int j = 0; j < len; j++) {
HC[i][j] = temp[len - j - 1];
}
HC[i][len] = '\0';
}
free(temp);
}
// 哈夫曼解码
void huffmanDecoding(HuffmanTree HT, int n, char *code, char *text)
{
int i, c = 2 * n - 1;
int len = strlen(code);
for (i = 0; i < len; i++) {
if (code[i] == '0') { // 如果是0,则遍历左子树
c = HT[c].lchild;
} else { // 如果是1,则遍历右子树
c = HT[c].rchild;
}
if (HT[c].lchild == 0 && HT[c].rchild == 0) { // 如果是叶子节点,则找到了一个字符
strncat(text, &code[i + 1 - strlen(HT[c].weight)], HT[c].weight); // 将该字符添加到结果中
c = 2 * n - 1; // 从根节点重新开始
}
}
}
int main()
{
int n, i;
int w[MAX_NODE];
HuffmanTree HT;
char *HC[MAX_NODE];
char code[MAX_NODE * MAX_NODE], text[MAX_NODE * MAX_NODE];
printf("请输入叶子节点的个数n:");
scanf("%d", &n);
printf("请输入%d个叶子节点的权值:", n);
for (i = 1; i <= n; i++) {
scanf("%d", &w[i]);
}
createHuffmanTree(&HT, w, n);
huffmanEncoding(HT, HC, n);
printf("请输入需要编码的字符串:");
scanf("%s", text);
int len = strlen(text);
for (i = 0; i < len; i++) {
for (int j = 1; j <= n; j++) {
if (text[i] == j + '0') { // 将字符转换为数字
strcat(code, HC[j]); // 拼接编码
break;
}
}
}
printf("编码结果为:%s\n", code);
memset(text, 0, sizeof(text)); // 清空text数组
huffmanDecoding(HT, n, code, text);
printf("解码结果为:%s\n", text);
return 0;
}
```
以上代码实现了哈夫曼树的构建、哈夫曼编码和哈夫曼解码,可以通过控制台输入叶子节点的权值和需要编码的字符串,输出编码和解码的结果。
阅读全文