帮我用c语言写一个利用Huffan编码实现文件压缩
时间: 2024-03-14 09:48:04 浏览: 57
好的,我可以为您提供一个简单的C语言实现。以下代码实现了文件的压缩和解压功能:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TREE_HT 256
#define MAX_FILENAME 100
// 定义哈夫曼树节点
struct HuffmanNode {
char data;
int freq;
struct HuffmanNode *left;
struct HuffmanNode *right;
};
// 定义哈夫曼编码
struct HuffmanCode {
char data;
char code[MAX_TREE_HT];
};
// 统计字符出现频率
void countFrequency(FILE *fp, int *freq) {
char ch;
while ((ch = fgetc(fp)) != EOF) {
freq[ch]++;
}
}
// 创建哈夫曼树节点
struct HuffmanNode *createNode(char data, int freq) {
struct HuffmanNode *node = (struct HuffmanNode *) malloc(sizeof(struct HuffmanNode));
node->data = data;
node->freq = freq;
node->left = node->right = NULL;
return node;
}
// 创建哈夫曼树
struct HuffmanNode *buildHuffmanTree(int *freq) {
int i;
struct HuffmanNode *node, *left, *right;
struct MinHeap *heap = createMinHeap(MAX_TREE_HT);
for (i = 0; i < MAX_TREE_HT; i++) {
if (freq[i] > 0) {
node = createNode((char) i, freq[i]);
insertMinHeap(heap, node);
}
}
while (heap->size > 1) {
left = deleteMinHeap(heap);
right = deleteMinHeap(heap);
node = createNode('\0', left->freq + right->freq);
node->left = left;
node->right = right;
insertMinHeap(heap, node);
}
node = deleteMinHeap(heap);
destroyMinHeap(heap);
return node;
}
// 生成哈夫曼编码
void generateHuffmanCode(struct HuffmanNode *node, char *code, int len, struct HuffmanCode *hCodes) {
if (node == NULL) {
return;
}
if (node->left == NULL && node->right == NULL) {
hCodes[node->data].data = node->data;
hCodes[node->data].code[len] = '\0';
strcpy(hCodes[node->data].code, code);
return;
}
code[len] = '0';
generateHuffmanCode(node->left, code, len + 1, hCodes);
code[len] = '1';
generateHuffmanCode(node->right, code, len + 1, hCodes);
}
// 将哈夫曼编码写入文件
void writeHuffmanCode(FILE *fp, struct HuffmanCode *hCodes, int *freq) {
int i, j;
char ch;
fwrite(freq, sizeof(int), MAX_TREE_HT, fp);
for (i = 0; i < MAX_TREE_HT; i++) {
if (freq[i] > 0) {
ch = (char) i;
fwrite(&ch, sizeof(char), 1, fp);
fwrite(hCodes[i].code, sizeof(char), strlen(hCodes[i].code), fp);
}
}
}
// 从文件中读取哈夫曼编码
struct HuffmanNode *readHuffmanCode(FILE *fp, int *freq) {
int i, j, len;
char ch, *code;
struct HuffmanNode *root = NULL;
struct HuffmanNode *node = NULL;
fread(freq, sizeof(int), MAX_TREE_HT, fp);
for (i = 0; i < MAX_TREE_HT; i++) {
if (freq[i] > 0) {
ch = (char) i;
code = (char *) malloc(sizeof(char) * (MAX_TREE_HT + 1));
fread(code, sizeof(char), MAX_TREE_HT, fp);
node = createNode(ch, freq[i]);
if (root == NULL) {
root = node;
}
for (j = 0, len = strlen(code); j < len; j++) {
if (code[j] == '0') {
if (node->left == NULL) {
node->left = createNode('\0', 0);
}
node = node->left;
} else if (code[j] == '1') {
if (node->right == NULL) {
node->right = createNode('\0', 0);
}
node = node->right;
}
}
free(code);
}
}
return root;
}
// 压缩文件
void compressFile(char *filename, struct HuffmanCode *hCodes) {
int i, len;
char ch, *code;
FILE *fpin, *fpout;
fpin = fopen(filename, "rb");
if (fpin == NULL) {
printf("Error: cannot open file %s\n", filename);
return;
}
len = strlen(filename);
filename[len - 3] = 'h';
filename[len - 2] = 'f';
filename[len - 1] = 'c';
fpout = fopen(filename, "wb");
if (fpout == NULL) {
printf("Error: cannot create file %s\n", filename);
return;
}
int freq[MAX_TREE_HT] = {0};
countFrequency(fpin, freq);
struct HuffmanNode *root = buildHuffmanTree(freq);
generateHuffmanCode(root, code, 0, hCodes);
writeHuffmanCode(fpout, hCodes, freq);
rewind(fpin);
code = (char *) malloc(sizeof(char) * (MAX_TREE_HT + 1));
while ((ch = fgetc(fpin)) != EOF) {
strcpy(code, hCodes[ch].code);
for (i = 0, len = strlen(code); i < len; i++) {
if (code[i] == '0') {
fwrite("0", sizeof(char), 1, fpout);
} else if (code[i] == '1') {
fwrite("1", sizeof(char), 1, fpout);
}
}
}
free(code);
fclose(fpin);
fclose(fpout);
printf("File %s is compressed successfully!\n", filename);
}
// 解压文件
void decompressFile(char *filename, struct HuffmanNode *root) {
int i;
char ch, bit;
FILE *fpin, *fpout;
fpin = fopen(filename, "rb");
if (fpin == NULL) {
printf("Error: cannot open file %s\n", filename);
return;
}
int freq[MAX_TREE_HT] = {0};
readHuffmanCode(fpin, freq);
root = readHuffmanCode(fpin, freq);
char newfilename[MAX_FILENAME];
int len = strlen(filename);
strncpy(newfilename, filename, len - 3);
newfilename[len - 3] = 'u';
newfilename[len - 2] = 'n';
newfilename[len - 1] = 'c';
fpout = fopen(newfilename, "wb");
if (fpout == NULL) {
printf("Error: cannot create file %s\n", newfilename);
return;
}
struct HuffmanNode *node = root;
while ((ch = fgetc(fpin)) != EOF) {
for (i = 7; i >= 0; i--) {
bit = (ch & (1 << i)) ? '1' : '0';
if (bit == '0') {
node = node->left;
} else if (bit == '1') {
node = node->right;
}
if (node->left == NULL && node->right == NULL) {
fwrite(&node->data, sizeof(char), 1, fpout);
node = root;
}
}
}
fclose(fpin);
fclose(fpout);
printf("File %s is decompressed successfully!\n", filename);
}
int main() {
int op;
char filename[MAX_FILENAME];
struct HuffmanCode hCodes[MAX_TREE_HT] = {{0}};
struct HuffmanNode *root = NULL;
while (1) {
printf("1. Compress file\n");
printf("2. Decompress file\n");
printf("3. Exit\n");
printf("Enter your choice: ");
scanf("%d", &op);
switch (op) {
case 1:
printf("Enter filename to compress: ");
scanf("%s", filename);
compressFile(filename, hCodes);
break;
case 2:
printf("Enter filename to decompress: ");
scanf("%s", filename);
decompressFile(filename, root);
break;
case 3:
exit(0);
}
}
return 0;
}
```
希望这个代码对您有帮助!
阅读全文