c语言哈夫曼编码解决文件压缩问题
时间: 2024-01-04 17:00:48 浏览: 97
C语言的哈夫曼编码是一种常用的文件压缩算法,它通过将出现频率较高的字符用较短的二进制编码表示,从而达到减小文件大小的目的。
哈夫曼编码的算法步骤如下:
1. 统计文件中每个字符出现的频率。
2. 根据字符的频率构建哈夫曼树,其中频率较低的字符在树中较深的位置。
3. 从哈夫曼树的根节点开始,对每个字符进行编码。向左走表示编码为0,向右走表示编码为1,直到达到字符所在的叶子节点。
4. 将每个字符的编码存储到压缩后的文件中。
5. 压缩后的文件中,除了存储编码后的字符序列,还需要保存用于解码的哈夫曼树结构。
6. 解压时,根据保存的哈夫曼树结构和编码后的字符序列,通过前缀匹配的方式逐步解码,恢复出原始的字符序列。
通过哈夫曼编码,频率较高的字符会被压缩为较短的二进制编码,从而减少了文件大小。相对于其他压缩算法,哈夫曼编码在压缩效率上具有一定优势。在C语言中,可以通过数据结构如树、优先队列等来实现哈夫曼编码算法,并通过文件操作读取和写入文件。
总之,C语言的哈夫曼编码是一种有效的文件压缩算法,通过统计字符频率,构建哈夫曼树并进行编码,可以实现对文件的有效压缩和解压缩。
相关问题
c语言哈夫曼编码压缩文件
C语言实现哈夫曼编码压缩文件的过程可以分为以下几个步骤:
1. 统计字符频率:从输入的文本文件中读取字符,并统计每个字符出现的频率。
2. 构建哈夫曼树:根据字符频率构建哈夫曼树。哈夫曼树是一种最优二叉树,其中频率较低的字符位于树的较低层,频率较高的字符位于树的较高层。
3. 生成哈夫曼编码表:通过遍历哈夫曼树,为每个字符生成对应的哈夫曼编码。哈夫曼编码是由0和1组成的二进制编码,用于表示每个字符。
4. 压缩文件:将输入的文本文件中的字符根据哈夫曼编码表进行编码,并将编码后的二进制数据写入输出文件。这样可以实现对文本文件的压缩。
5. 计算压缩率:通过比较压缩后的文件大小与原始文件大小,计算出压缩率。压缩率越高,表示压缩效果越好。
6. 解压文件:读取压缩文件中的二进制数据,并根据哈夫曼编码表进行解码,将解码后的字符写入输出文件。这样可以实现对压缩文件的解压缩。
以下是一个C语言实现哈夫曼编码压缩文件的示例代码:
```c
// 哈夫曼树节点结构体
typedef struct Node {
char data; // 字符
int freq; // 频率
struct Node* left;
struct Node* right;
} Node;
// 构建哈夫曼树
Node* buildHuffmanTree(char* text);
// 生成哈夫曼编码表
void generateHuffmanCodes(Node* root, char* code, int depth, char** codes);
// 压缩文件
void compressFile(char* inputFile, char* outputFile, char** codes);
// 解压文件
void decompressFile(char* inputFile, char* outputFile, Node* root);
// 计算文件大小
long getFileSize(FILE* file);
// 计算压缩率
float calculateCompressionRatio(long originalSize, long compressedSize);
int main() {
char* inputFile = "input.txt";
char* compressedFile = "compressed.bin";
char* decompressedFile = "decompressed.txt";
// 构建哈夫曼树
Node* root = buildHuffmanTree(inputFile);
// 生成哈夫曼编码表
char* codes[256];
generateHuffmanCodes(root, "", 0, codes);
// 压缩文件
compressFile(inputFile, compressedFile, codes);
// 解压文件
decompressFile(compressedFile, decompressedFile, root);
// 计算文件大小和压缩率
FILE* inputFilePtr = fopen(inputFile, "rb");
FILE* compressedFilePtr = fopen(compressedFile, "rb");
long originalSize = getFileSize(inputFilePtr);
long compressedSize = getFileSize(compressedFilePtr);
float compressionRatio = calculateCompressionRatio(originalSize, compressedSize);
printf("Compression ratio: %.2f%%\n", compressionRatio);
// 释放内存
// ...
return 0;
}
```
c语言哈夫曼编码压缩文件代码
下面是一个简单的C语言哈夫曼编码压缩文件的代码示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义哈夫曼树节点结构体
typedef struct huffman_node {
unsigned char symbol; // 字符
int frequency; // 频率
struct huffman_node *left; // 左节点
struct huffman_node *right; // 右节点
} HuffmanNode;
// 定义哈夫曼编码结构体
typedef struct huffman_code {
unsigned char symbol; // 字符
char *code; // 编码
} HuffmanCode;
// 定义哈夫曼树节点队列结构体
typedef struct huffman_queue {
int size; // 队列大小
int capacity; // 队列容量
HuffmanNode **data; // 哈夫曼树节点数组
} HuffmanQueue;
// 创建哈夫曼树节点
HuffmanNode *create_huffman_node(unsigned char symbol, int frequency) {
HuffmanNode *node = malloc(sizeof(HuffmanNode));
node->symbol = symbol;
node->frequency = frequency;
node->left = NULL;
node->right = NULL;
return node;
}
// 销毁哈夫曼树节点
void destroy_huffman_node(HuffmanNode *node) {
free(node);
}
// 创建哈夫曼编码
HuffmanCode *create_huffman_code(unsigned char symbol, char *code) {
HuffmanCode *huffman_code = malloc(sizeof(HuffmanCode));
huffman_code->symbol = symbol;
huffman_code->code = code;
return huffman_code;
}
// 销毁哈夫曼编码
void destroy_huffman_code(HuffmanCode *huffman_code) {
free(huffman_code->code);
free(huffman_code);
}
// 创建哈夫曼树节点队列
HuffmanQueue *create_huffman_queue(int capacity) {
HuffmanQueue *queue = malloc(sizeof(HuffmanQueue));
queue->size = 0;
queue->capacity = capacity;
queue->data = malloc(sizeof(HuffmanNode *) * capacity);
return queue;
}
// 销毁哈夫曼树节点队列
void destroy_huffman_queue(HuffmanQueue *queue) {
for (int i = 0; i < queue->size; i++) {
destroy_huffman_node(queue->data[i]);
}
free(queue->data);
free(queue);
}
// 获取哈夫曼树节点队列中频率最小的节点
HuffmanNode *get_min_frequency_node(HuffmanQueue *queue) {
int min_frequency = queue->data[0]->frequency;
int min_frequency_index = 0;
for (int i = 1; i < queue->size; i++) {
if (queue->data[i]->frequency < min_frequency) {
min_frequency = queue->data[i]->frequency;
min_frequency_index = i;
}
}
return queue->data[min_frequency_index];
}
// 添加哈夫曼树节点到队列中
void enqueue_huffman_node(HuffmanQueue *queue, HuffmanNode *node) {
if (queue->size == queue->capacity) {
fprintf(stderr, "Error: Huffman queue is full.\n");
exit(EXIT_FAILURE);
}
queue->data[queue->size++] = node;
}
// 从队列中删除哈夫曼树节点
void dequeue_huffman_node(HuffmanQueue *queue, int index) {
destroy_huffman_node(queue->data[index]);
for (int i = index; i < queue->size - 1; i++) {
queue->data[i] = queue->data[i + 1];
}
queue->size--;
}
// 构建哈夫曼树
HuffmanNode *build_huffman_tree(HuffmanQueue *queue) {
while (queue->size > 1) {
HuffmanNode *left = get_min_frequency_node(queue);
dequeue_huffman_node(queue, 0);
HuffmanNode *right = get_min_frequency_node(queue);
dequeue_huffman_node(queue, 0);
HuffmanNode *parent = create_huffman_node(0, left->frequency + right->frequency);
parent->left = left;
parent->right = right;
enqueue_huffman_node(queue, parent);
}
return queue->data[0];
}
// 递归获取哈夫曼编码
void get_huffman_code_recursion(HuffmanNode *node, char *code, int code_length, HuffmanCode **huffman_codes) {
if (node->left == NULL && node->right == NULL) {
char *huffman_code = malloc(sizeof(char) * (code_length + 1));
memcpy(huffman_code, code, sizeof(char) * code_length);
huffman_code[code_length] = '\0';
HuffmanCode *huffman_code_object = create_huffman_code(node->symbol, huffman_code);
huffman_codes[node->symbol] = huffman_code_object;
return;
}
code[code_length++] = '0';
get_huffman_code_recursion(node->left, code, code_length, huffman_codes);
code[--code_length] = '1';
get_huffman_code_recursion(node->right, code, code_length, huffman_codes);
}
// 获取哈夫曼编码
HuffmanCode **get_huffman_codes(HuffmanNode *root) {
HuffmanCode **huffman_codes = malloc(sizeof(HuffmanCode *) * 256);
char code[256];
get_huffman_code_recursion(root, code, 0, huffman_codes);
return huffman_codes;
}
// 压缩文件
void compress_file(char *input_file_path, char *output_file_path, HuffmanCode **huffman_codes) {
// 打开输入文件
FILE *input_file = fopen(input_file_path, "rb");
if (input_file == NULL) {
fprintf(stderr, "Error: Failed to open input file.\n");
exit(EXIT_FAILURE);
}
// 统计每个字符出现的频率
int frequency[256] = {0};
int character;
while ((character = fgetc(input_file)) != EOF) {
frequency[character]++;
}
// 关闭输入文件
fclose(input_file);
// 创建哈夫曼树节点队列
HuffmanQueue *queue = create_huffman_queue(256);
for (int i = 0; i < 256; i++) {
if (frequency[i] > 0) {
HuffmanNode *node = create_huffman_node(i, frequency[i]);
enqueue_huffman_node(queue, node);
}
}
// 构建哈夫曼树
HuffmanNode *root = build_huffman_tree(queue);
// 获取哈夫曼编码
HuffmanCode **codes = get_huffman_codes(root);
// 打开输出文件
FILE *output_file = fopen(output_file_path, "wb");
if (output_file == NULL) {
fprintf(stderr, "Error: Failed to open output file.\n");
exit(EXIT_FAILURE);
}
// 写入哈夫曼树节点数量
int node_count = queue->size;
fwrite(&node_count, sizeof(int), 1, output_file);
// 写入哈夫曼树节点
for (int i = 0; i < node_count; i++) {
fwrite(&queue->data[i]->symbol, sizeof(unsigned char), 1, output_file);
fwrite(&queue->data[i]->frequency, sizeof(int), 1, output_file);
}
// 打开输入文件
input_file = fopen(input_file_path, "rb");
if (input_file == NULL) {
fprintf(stderr, "Error: Failed to open input file.\n");
exit(EXIT_FAILURE);
}
// 写入压缩后的文件
unsigned char buffer = 0;
int buffer_length = 0;
while ((character = fgetc(input_file)) != EOF) {
HuffmanCode *huffman_code = codes[character];
for (int i = 0; i < strlen(huffman_code->code); i++) {
if (huffman_code->code[i] == '0') {
buffer <<= 1;
} else {
buffer <<= 1;
buffer |= 1;
}
buffer_length++;
if (buffer_length == 8) {
fwrite(&buffer, sizeof(unsigned char), 1, output_file);
buffer = 0;
buffer_length = 0;
}
}
}
if (buffer_length > 0) {
buffer <<= (8 - buffer_length);
fwrite(&buffer, sizeof(unsigned char), 1, output_file);
}
// 关闭输入文件和输出文件
fclose(input_file);
fclose(output_file);
// 销毁哈夫曼树节点队列、哈夫曼编码和哈夫曼树
destroy_huffman_queue(queue);
for (int i = 0; i < 256; i++) {
if (huffman_codes[i] != NULL) {
destroy_huffman_code(huffman_codes[i]);
}
if (codes[i] != NULL) {
destroy_huffman_code(codes[i]);
}
}
free(codes);
destroy_huffman_node(root);
}
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s input_file_path output_file_path\n", argv[0]);
exit(EXIT_FAILURE);
}
HuffmanCode **huffman_codes = malloc(sizeof(HuffmanCode *) * 256);
compress_file(argv[1], argv[2], huffman_codes);
free(huffman_codes);
return 0;
}
```
在上面的代码中,我们定义了一个`HuffmanNode`结构体来表示哈夫曼树节点,其中包括一个字符、一个频率、一个左节点和一个右节点。我们还定义了一个`HuffmanCode`结构体来表示哈夫曼编码,其中包括一个字符和一个编码字符串。我们还定义了一个`HuffmanQueue`结构体来表示哈夫曼树节点队列,其中包括一个大小、一个容量和一个哈夫曼树节点数组。我们实现了一些函数来创建和销毁这些结构体,还实现了一些函数来操作哈夫曼树节点队列和构建哈夫曼树。最后,我们实现了一个`compress_file`函数来压缩文件,其中我们使用了上述函数来构建哈夫曼树和获取哈夫曼编码,并将压缩后的文件写入输出文件。
阅读全文