hfm编码译/码器

利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成 本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编 /译码系统。

基本要求

  • I:初始化(Initialization)。从终端读入字符集大小n , 以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
  • E:编码(Encoding)。利用以建好的哈夫曼树(如不在内存,则从文件hfmTree中读人),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
  • D: 译码(Decoding)。利用已建好的哈夫曼树将文件 CodeFile 中的代码进行译码,结果存入文件TextFile中。
  • P:打印代码文件(Print)。将文件CodeFile以紧凑格式显示在终端上,每行 50 个代码。同时将此字符形式的编码文件写入文件 CodePrin 中。
  • T:打印哈夫曼树(Tree printing)。将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHARACTERS 256
#define MAX_BIT_LENGTH 1000
typedef struct Node {
char data;
int freq;
struct Node* left;
struct Node* right;
} Node;
typedef struct {
Node* root;
} HuffmanTree;
typedef struct {
char code[MAX_BIT_LENGTH];
int length;
} Code;
Node* createNode(char data, int freq) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) {
printf("内存分配失败!\n");
exit(EXIT_FAILURE);
}
newNode->data = data;
newNode->freq = freq;
newNode->left = newNode->right = NULL;
return newNode;
}
void printTree(Node* root, int level) {
if (root != NULL) {
printTree(root->right, level + 1);
for (int i = 0; i < level; i++) printf(" ");
printf("%c(%d)\n", root->data, root->freq);
printTree(root->left, level + 1);
}
}
void encodeHelper(Node* root, char* code, int index, Code* codes[]) {
if (root->left) {
code[index] = '0';
encodeHelper(root->left, code, index + 1, codes);
}
if (root->right) {
code[index] = '1';
encodeHelper(root->right, code, index + 1, codes);
}
if (!root->left && !root->right) {
code[index] = '\0';
Code* newCode = (Code*)malloc(sizeof(Code));
strcpy(newCode->code, code);
newCode->length = index;
codes[(int)root->data] = newCode;
}
}
void encode(HuffmanTree* tree, char* input, char* output) {
FILE* inputFile = fopen(input, "r");
FILE* outputFile = fopen(output, "wb");
if (!inputFile || !outputFile) {
printf("文件打开失败!\n");
exit(EXIT_FAILURE);
}
Code* codes[MAX_CHARACTERS] = { NULL };
char code[MAX_BIT_LENGTH];
encodeHelper(tree->root, code, 0, codes);
char c;
while ((c = fgetc(inputFile)) != EOF) {
Code* currentCode = codes[(int)c];
fwrite(currentCode->code, sizeof(char), currentCode->length, outputFile);
}
fclose(inputFile);
fclose(outputFile);
}
void decode(HuffmanTree* tree, char* input, char* output) {
FILE* inputFile = fopen(input, "rb");
FILE* outputFile = fopen(output, "w");
if (!inputFile || !outputFile) {
printf("文件打开失败!\n");
exit(EXIT_FAILURE);
}
Node* currentNode = tree->root;
char bit;
while ((bit = fgetc(inputFile)) != EOF) {
if (bit == '0') {
currentNode = currentNode->left;
}
else if (bit == '1') {
currentNode = currentNode->right;
}
if (!currentNode->left && !currentNode->right) {
fputc(currentNode->data, outputFile);
currentNode = tree->root;
}
}
fclose(inputFile);
fclose(outputFile);
}
void printCodesToFile(HuffmanTree* tree, char* output) {
FILE* outputFile = fopen(output, "w");
if (!outputFile) {
printf("文件打开失败!\n");
exit(EXIT_FAILURE);
}
char code[MAX_BIT_LENGTH] = "";
encodeHelper(tree->root, code, 0, NULL);
fprintf(outputFile, "Huffman Codes:\n");
for (int i = 0; i < MAX_CHARACTERS; i++) {
if (tree->root[i].freq > 0) {
fprintf(outputFile, "%c: %s\n", (char)i, code);
}
}
fclose(outputFile);
}
int main() {
int n;
printf("输入字符集中的字符数: ");
scanf("%d", &n);
char characters[MAX_CHARACTERS];
int frequencies[MAX_CHARACTERS];
printf("输入字符及其频率:\n");
for (int i = 0; i < n; i++) {
scanf(" %c %d", &characters[i], &frequencies[i]);
}
// Build Huffman tree
Node* nodes[MAX_CHARACTERS];
for (int i = 0; i < n; i++) {
nodes[i] = createNode(characters[i], frequencies[i]);
}
for (int i = 0; i < n - 1; i++) {
int min1 = INT_MAX, min2 = INT_MAX;
int minIndex1 = -1, minIndex2 = -1;
for (int j = 0; j < n + i; j++) {
if (nodes[j]->freq < min1) {
min2 = min1;
minIndex2 = minIndex1;
min1 = nodes[j]->freq;
minIndex1 = j;
}
else if (nodes[j]->freq < min2) {
min2 = nodes[j]->freq;
minIndex2 = j;
}
}
Node* newNode = createNode('\0', min1 + min2);
newNode->left = nodes[minIndex1];
newNode->right = nodes[minIndex2];
nodes[minIndex1] = newNode;
nodes[minIndex2] = nodes[n + i];
}
HuffmanTree tree = { nodes[0] };
// Encode
encode(&tree, "ToBeTran", "CodeFile");
// Decode
decode(&tree, "CodeFile", "TextFile");
// Print codes
printCodesToFile(&tree, "CodePrint");
// Print Huffman tree
printTree(tree.root, 0);
return 0;
}

1
2
3
4
输入字符集中的字符数: 26
输入字符及其频率:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
64 13 22 32 103 21 15 47 57 1 5 32 20 57 63 15 1 48 51 80 23 8 18 1 16 1