c语言哈夫曼编码压缩文件代码
时间: 2023-10-14 14:25:29 浏览: 133
用哈夫曼编码实现文件压缩(代码+报告)
下面是C语言实现的哈夫曼编码压缩文件代码,包括哈夫曼树的构建、编码、压缩和解压缩:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NODE 256
#define MAX_BITS 16
typedef struct {
unsigned char bits[MAX_BITS];
int len;
} huff_code;
typedef struct {
int freq;
huff_code code;
} huff_node;
int get_min_freq(huff_node *nodes, int n, int *pmin1, int *pmin2)
{
int i, min1, min2;
min1 = min2 = -1;
for (i = 0; i < n; i++) {
if (nodes[i].freq > 0) {
if (min1 == -1 || nodes[i].freq < nodes[min1].freq) {
min2 = min1;
min1 = i;
} else if (min2 == -1 || nodes[i].freq < nodes[min2].freq) {
min2 = i;
}
}
}
*pmin1 = min1;
*pmin2 = min2;
return (min1 != -1 && min2 != -1);
}
void build_huff_tree(huff_node *nodes, int n)
{
int i, min1, min2, parent;
while (get_min_freq(nodes, n, &min1, &min2)) {
parent = n;
nodes[parent].freq = nodes[min1].freq + nodes[min2].freq;
nodes[parent].code.len = 0;
nodes[min1].code.bits[nodes[min1].code.len++] = 0;
nodes[min2].code.bits[nodes[min2].code.len++] = 1;
for (i = 0; i < nodes[min1].code.len; i++) {
nodes[parent].code.bits[nodes[parent].code.len++] =
nodes[min1].code.bits[i];
}
for (i = 0; i < nodes[min2].code.len; i++) {
nodes[parent].code.bits[nodes[parent].code.len++] =
nodes[min2].code.bits[i];
}
nodes[min1].freq = nodes[min2].freq = 0;
}
}
int encode_huff_file(const char *infile, const char *outfile)
{
FILE *fin, *fout;
int i, j, ch, bits, bit_count, len, freq[MAX_NODE] = {0};
huff_node nodes[MAX_NODE * 2 - 1];
if ((fin = fopen(infile, "rb")) == NULL)
return -1;
while ((ch = fgetc(fin)) != EOF) {
freq[ch]++;
}
fclose(fin);
len = 0;
for (i = 0; i < MAX_NODE; i++) {
if (freq[i] > 0) {
nodes[len].freq = freq[i];
nodes[len].code.len = 0;
len++;
}
}
build_huff_tree(nodes, len);
if ((fout = fopen(outfile, "wb")) == NULL)
return -1;
fwrite(&len, sizeof(len), 1, fout);
for (i = 0; i < len; i++) {
fwrite(&nodes[i].freq, sizeof(nodes[i].freq), 1, fout);
}
if ((fin = fopen(infile, "rb")) == NULL)
return -1;
bits = 0;
bit_count = 0;
while ((ch = fgetc(fin)) != EOF) {
for (i = 0; i < len; i++) {
if (nodes[i].code.len == 0)
continue;
if (i == ch) {
for (j = 0; j < nodes[i].code.len; j++) {
bits <<= 1;
if (nodes[i].code.bits[j])
bits |= 1;
bit_count++;
if (bit_count == 8) {
fputc(bits, fout);
bits = 0;
bit_count = 0;
}
}
}
}
}
if (bit_count > 0) {
bits <<= 8 - bit_count;
fputc(bits, fout);
}
fclose(fin);
fclose(fout);
return 0;
}
int decode_huff_file(const char *infile, const char *outfile)
{
FILE *fin, *fout;
int i, j, ch, bits, bit_count, len, freq[MAX_NODE] = {0};
huff_node nodes[MAX_NODE * 2 - 1];
if ((fin = fopen(infile, "rb")) == NULL)
return -1;
fread(&len, sizeof(len), 1, fin);
for (i = 0; i < len; i++) {
fread(&nodes[i].freq, sizeof(nodes[i].freq), 1, fin);
nodes[i].code.len = 0;
}
build_huff_tree(nodes, len);
if ((fout = fopen(outfile, "wb")) == NULL)
return -1;
bits = 0;
bit_count = 0;
while ((ch = fgetc(fin)) != EOF) {
for (i = 0; i < 8; i++) {
bits <<= 1;
bits |= ((ch & (1 << (7 - i))) ? 1 : 0);
bit_count++;
for (j = 0; j < len; j++) {
if (nodes[j].code.len == bit_count &&
memcmp(nodes[j].code.bits, &bits, bit_count / 8) == 0) {
fputc(j, fout);
bits = 0;
bit_count = 0;
break;
}
}
}
}
fclose(fin);
fclose(fout);
return 0;
}
int main(int argc, char *argv[])
{
int ret;
if (argc != 4) {
fprintf(stderr, "Usage: %s c/d infile outfile\n", argv[0]);
return 1;
}
if (*argv[1] == 'c') {
ret = encode_huff_file(argv[2], argv[3]);
} else if (*argv[1] == 'd') {
ret = decode_huff_file(argv[2], argv[3]);
} else {
fprintf(stderr, "Invalid option\n");
return 1;
}
if (ret < 0) {
fprintf(stderr, "Failed to process file\n");
return 1;
}
return 0;
}
```
注意事项:
- 压缩文件必须是二进制文件,不能是纯文本文件。
- 哈夫曼编码中使用的字符集必须是固定的,这里使用了256个字符。如果要处理其他字符集,需要修改代码中的MAX_NODE宏定义。
阅读全文