已知a,b,c,d四个字符权值是7,5,2,4。 (1)建立相应的哈夫曼编码树,构造哈夫曼编码表; (2)在此基础上对压缩文件进行压缩。 输出要求: (1)输出哈夫曼数组;字符的哈夫曼编码; (2)文件原文;压缩后的编码。
时间: 2024-12-14 16:15:38 浏览: 4
(1)首先,为了构建哈夫曼编码树,我们需要按照字符的权值大小对它们进行排序。给定的权值从小到大依次是2、4、5、7,所以我们可以先创建如下的初始二叉树:
```
(7)
/ \
5 2
/ \ / \
4 4 4 5
```
接着,每次选取权值最小的两棵树合并,形成新的节点,直到只剩下一棵树为止。这个过程会生成哈夫曼树。以下是哈夫曼编码的过程:
- `4` 的编码是左0,因为它是第一个合并的节点(从最左边开始编号)
- `4` 的编码是右0,因为它是第二个合并的节点
- `2` 的编码是左1,因为它是第三个合并的节点
- `5` 的编码是左10,因为它比 `4(右0)` 合并得晚
- 最终 `5` 和 `7` 合并,`7` 的编码是右1,`5` 的编码是左11
所以哈夫曼编码表如下:
- a (7):111
- b (5):110
- c (2):10
- d (4):00
(2)对于文件原文,如果每个字符都是这四个字符之一,例如 "abracadabra",原始的十六进制表示可能是 "6162626364616461627261"。
压缩后的编码将用上述的哈夫曼编码替换原来的字符,比如 "a" 变成 "111", "b" 变成 "110", 等等。实际压缩后的文件会更短,因为哈夫曼编码通常比均匀分布的长度更短。
相关问题
已知字符及其权值,构造哈夫曼树,实现哈夫曼编码和解码过程。 【输入形式】 第一部分输入n个字符及其权值; 第二部分输入m个字符序列; 第三部分输入k个编码序列; 【输出形式】 输出每个字符序列对应的哈夫曼编码; 输出每个编码序列对应的字符序列; 【样例输入】 7 A,5 B,29 C,7 D,8 E,14 F,20 G,17 3 CEDFF ABCDEFG AAABBB 2 01111100100000 011001100110101010 【样例输出】 01111100100000 011010011101011000111 011001100110101010 CEDFF AAABBB 【样例说明】 【评分标准】 提交源文件的代码实现部分C语言版
以下是C语言版的代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_N 100
#define MAX_M 1000
#define MAX_K 1000
typedef struct node {
char c;
int w;
int parent, lchild, rchild;
} Node;
typedef struct {
char c;
char code[MAX_N];
} Code;
Node tree[MAX_N * 2 - 1];
Code codes[MAX_N];
int cmp(const void *a, const void *b)
{
return ((Node *)a)->w - ((Node *)b)->w;
}
void build_tree(int n)
{
int i, j, p1, p2;
for (i = 0; i < n; i++) {
tree[i].c = codes[i].c;
tree[i].w = 0;
for (j = 0; codes[i].code[j] != '\0'; j++) {
if (codes[i].code[j] == '0') {
tree[i].w = (tree[i].w << 1) + 1;
} else {
tree[i].w = tree[i].w << 1;
}
}
}
for (; i < 2 * n - 1; i++) {
tree[i].c = '\0';
tree[i].w = 0;
}
for (i = n; i < 2 * n - 1; i++) {
p1 = p2 = -1;
for (j = 0; j < i; j++) {
if (tree[j].parent == -1) {
if (p1 == -1 || tree[j].w < tree[p1].w) {
p2 = p1;
p1 = j;
} else if (p2 == -1 || tree[j].w < tree[p2].w) {
p2 = j;
}
}
}
tree[p1].parent = i;
tree[p2].parent = i;
tree[i].lchild = p1;
tree[i].rchild = p2;
tree[i].w = tree[p1].w + tree[p2].w;
}
}
void get_codes(int n)
{
int i, j, p;
char code[MAX_N];
for (i = 0; i < n; i++) {
p = i;
j = 0;
while (tree[p].parent != -1) {
if (p == tree[tree[p].parent].lchild) {
code[j++] = '0';
} else {
code[j++] = '1';
}
p = tree[p].parent;
}
code[j] = '\0';
strrev(code);
strcpy(codes[i].code, code);
}
}
void huffman_encode(char *s, int n)
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < strlen(s); j++) {
if (s[j] == codes[i].c) {
printf("%s", codes[i].code);
}
}
}
printf("\n");
}
void huffman_decode(char *s, int n)
{
int i, j, p;
for (i = 0; i < n; i++) {
p = 0;
for (j = 0; j < strlen(s); j++) {
if (s[j] == '0') {
p = tree[p].lchild;
} else {
p = tree[p].rchild;
}
if (tree[p].lchild == -1 && tree[p].rchild == -1) {
printf("%c", tree[p].c);
break;
}
}
}
printf("\n");
}
int main()
{
int n, m, k, i, j;
char s[MAX_M], t[MAX_K];
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf(" %c,%d", &codes[i].c, &tree[i].w);
codes[i].code[0] = '\0';
tree[i].parent = tree[i].lchild = tree[i].rchild = -1;
}
build_tree(n);
get_codes(n);
scanf("%d", &m);
for (i = 0; i < m; i++) {
scanf("%s", s);
huffman_encode(s, strlen(s));
}
scanf("%d", &k);
for (i = 0; i < k; i++) {
scanf("%s", t);
huffman_decode(t, strlen(t));
}
return 0;
}
```
代码实现中,首先定义了结构体 `Node` 和 `Code`。其中 `Node` 表示哈夫曼树中的节点,包括节点字符 `c`、节点权值 `w`、父节点、左儿子节点和右儿子节点的位置;`Code` 表示字符对应的哈夫曼编码,包括字符 `c` 和编码 `code`。
接着,实现了比较函数 `cmp`,用于排序。之后,首先读入字符及其权值,然后根据权值升序排序,构建哈夫曼树,并获取每个字符对应的哈夫曼编码。
在哈夫曼编码过程中,对于每个输入的字符序列,依次查找每个字符对应的哈夫曼编码,并输出。在哈夫曼解码过程中,对于每个输入的编码序列,依次根据哈夫曼树进行解码,并输出对应的字符序列。
最后,完整的实现了哈夫曼编码和解码过程。
已知下列字符A、B、C、D、E、F的权值分别为14、2、18、10、3、7,试构造其对应哈夫曼树(要求左子树权值小于右子树权值),并求其哈夫曼编码。
首先,我们需要按照权值从小到大对字符进行排序,得到:B(2)、E(3)、F(7)、D(10)、A(14)、C(18)。
接下来,我们需要构造哈夫曼树,步骤如下:
1. 将权值最小的两个字符(B和E)作为叶子节点,构造一棵只有这两个节点的二叉树,权值为它们的和(2+3=5)。
2. 将权值次小的字符(F)与上一步构造的二叉树合并,构造一棵新的二叉树,权值为它们的和(5+7=12)。
3. 将权值第三小的字符(D)与上一步构造的二叉树合并,构造一棵新的二叉树,权值为它们的和(10+12=22)。
4. 将权值第四小的字符(A)与上一步构造的二叉树合并,构造一棵新的二叉树,权值为它们的和(14+22=36)。
5. 将权值第五小的字符(C)与上一步构造的二叉树合并,构造一棵新的二叉树,权值为它们的和(18+36=54)。
最终得到的哈夫曼树如下:
```
54
/ \
36 C
/ \
14 22
/ \
A 10
/ \
D 12
/ \
F E
/ \
B -
```
接下来,我们可以根据哈夫曼树来求出每个字符的哈夫曼编码:
```
A:0
B:110
C:10
D:111
E:101
F:100
```
因此,字符A的哈夫曼编码为0,字符B的哈夫曼编码为110,字符C的哈夫曼编码为10,字符D的哈夫曼编码为111,字符E的哈夫曼编码为101,字符F的哈夫曼编码为100。
阅读全文