c语言哈夫曼编码译码系统
c语言
一个完整的系统具有以下功能:
(1)I:初始化(Initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
(2)E:编码(Encoding)。利用已建好的哈夫曼树(如不在内存,则从文件htmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
(3)D:译码(Decoding)。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
(4)P:打印代码文件(Print)。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
(5)T:打印哈夫曼树(TreePrinting)。将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
3)测试数据
新建一个.txt文件,用来存放待处理的数据,这些数据为ASCII码值的集合,而且每种字符的数量并不能相同。本实验拟设其中的数据为1个a,两个b,三个c,四个d,五个e,六个f。
以下是一个简单的C语言实现的哈夫曼编码译码系统的代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义哈夫曼树节点
typedef struct Node {
unsigned char ch;
int weight;
struct Node* left;
struct Node* right;
} Node;
// 定义哈夫曼编码表
typedef struct {
unsigned char ch;
char code[256];
} CodeTable;
// 初始化哈夫曼树
Node* initHuffmanTree(int n, unsigned char* chars, int* weights) {
Node** nodes = (Node**)malloc(n * sizeof(Node*));
for (int i = 0; i < n; i++) {
nodes[i] = (Node*)malloc(sizeof(Node));
nodes[i]->ch = chars[i];
nodes[i]->weight = weights[i];
nodes[i]->left = NULL;
nodes[i]->right = NULL;
}
while (n > 1) {
int min1 = 0, min2 = 1;
if (nodes[min1]->weight > nodes[min2]->weight) {
int temp = min1;
min1 = min2;
min2 = temp;
}
for (int i = 2; i < n; i++) {
if (nodes[i]->weight < nodes[min1]->weight) {
min2 = min1;
min1 = i;
} else if (nodes[i]->weight < nodes[min2]->weight) {
min2 = i;
}
}
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->ch = 0;
newNode->weight = nodes[min1]->weight + nodes[min2]->weight;
newNode->left = nodes[min1];
newNode->right = nodes[min2];
nodes[min1] = newNode;
nodes[min2] = nodes[n - 1];
n--;
}
return nodes[0];
}
// 生成哈夫曼编码表
void generateCodeTable(Node* root, CodeTable* table, char* code, int depth) {
if (root->left == NULL && root->right == NULL) {
code[depth] = '\0';
for (int i = 0; i < 256; i++) {
if (table[i].ch == root->ch) {
strcpy(table[i].code, code);
break;
}
}
} else {
code[depth] = '0';
generateCodeTable(root->left, table, code, depth + 1);
code[depth] = '1';
generateCodeTable(root->right, table, code, depth + 1);
}
}
// 编码
void encode(Node* root, CodeTable* table, char* text, FILE* outputFile) {
char* code = (char*)malloc(256 * sizeof(char));
int index = 0;
for (int i = 0; text[i] != '\0'; i++) {
for (int j = 0; j < 256; j++) {
if (table[j].ch == text[i]) {
strcpy(code + index, table[j].code);
index += strlen(table[j].code);
break;
}
}
}
code[index] = '\0';
fprintf(outputFile, "%s", code);
free(code);
}
// 译码
void decode(Node* root, char* code, FILE* outputFile) {
Node* curr = root;
for (int i = 0; code[i] != '\0'; i++) {
if (code[i] == '0') {
curr = curr->left;
} else {
curr = curr->right;
}
if (curr->left == NULL && curr->right == NULL) {
fprintf(outputFile, "%c", curr->ch);
curr = root;
}
}
}
// 打印代码文件
void printCodeFile(FILE* codeFile) {
int count = 0;
unsigned char ch;
while ((ch = fgetc(codeFile)) != EOF) {
printf("%c", ch);
count++;
if (count % 50 == 0) {
printf("\n");
}
}
printf("\n");
}
// 打印哈夫曼树
void printHuffmanTree(Node* root, int depth) {
if (root == NULL) {
return;
}
printHuffmanTree(root->right, depth + 1);
for (int i = 0; i < depth; i++) {
printf(" ");
}
if (root->ch == 0) {
printf("*\n");
} else {
printf("%c\n", root->ch);
}
printHuffmanTree(root->left, depth + 1);
}
int main() {
int n;
printf("Enter the number of characters: ");
scanf("%d", &n);
unsigned char* chars = (unsigned char*)malloc(n * sizeof(unsigned char));
int* weights = (int*)malloc(n * sizeof(int));
printf("Enter the characters and weights:\n");
for (int i = 0; i < n; i++) {
scanf(" %c %d", &chars[i], &weights[i]);
}
Node* root = initHuffmanTree(n, chars, weights);
CodeTable* table = (CodeTable*)malloc(256 * sizeof(CodeTable));
char code[256];
generateCodeTable(root, table, code, 0);
FILE* hfmTreeFile = fopen("hfmTree", "w");
fwrite(root, sizeof(Node), 1, hfmTreeFile);
fclose(hfmTreeFile);
FILE* codeFile = fopen("CodeFile", "w");
char text[256];
printf("Enter the text to be encoded: ");
scanf(" %[^\n]", text);
encode(root, table, text, codeFile);
fclose(codeFile);
codeFile = fopen("CodeFile", "r");
printf("CodeFile content:\n");
printCodeFile(codeFile);
fclose(codeFile);
FILE* textFile = fopen("TextFile", "w");
codeFile = fopen("CodeFile", "r");
char codeText[256];
fscanf(codeFile, "%s", codeText);
decode(root, codeText, textFile);
fclose(codeFile);
fclose(textFile);
FILE* treePrintFile = fopen("TreePrint", "w");
printHuffmanTree(root, 0);
fclose(treePrintFile);
free(chars);
free(weights);
free(table);
return 0;
}
以上代码实现了一个简单的哈夫曼编码译码系统。你可以根据自己的需求进行修改和完善。请注意,此代码示例中的输入和输出文件名是固定的,你可以根据需要进行调整。同时,该示例中使用的是字符型的权值,如果需要处理其他类型的权值,请适当修改代码。
希望以上代码能帮助到你实现哈夫曼编码译码系统。如果有任何问题,请随时向我提问。