用c语言写一个代码,输入一串字符串,根据给定的字符串中字符出现的频率建立相应的哈夫曼树,构造哈夫曼编码表,在此基础上可以对压缩文件进行压缩,同时可以对压缩后的二进制编码文件进行解压
时间: 2024-03-21 15:44:28 浏览: 108
hafuman.rar_Huffman coding_hafuman_huffman_哈夫曼树_哈夫曼树 编码
好的,以下是一个基于C语言的实现,实现了输入字符串后建立哈夫曼树,并构造哈夫曼编码表的功能。同时也提供了对压缩文件进行压缩和解压缩的功能。注意,以下代码仅供参考,实际使用时可能需要根据具体场景进行修改和完善。
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#define MAX_LEN 256
typedef struct HuffmanNode {
char val;
int freq;
struct HuffmanNode* left;
struct HuffmanNode* right;
} HuffmanNode;
typedef struct CodeTable {
char ch;
char* code;
} CodeTable;
CodeTable code_table[MAX_LEN];
int code_table_size = 0;
void print_code_table() {
printf("Huffman code table:\n");
for (int i = 0; i < code_table_size; i++) {
printf("%c: %s\n", code_table[i].ch, code_table[i].code);
}
}
void free_huffman_tree(HuffmanNode* root) {
if (root) {
free_huffman_tree(root->left);
free_huffman_tree(root->right);
free(root);
}
}
int cmp_node(const void* a, const void* b) {
HuffmanNode* node1 = *(HuffmanNode**)a;
HuffmanNode* node2 = *(HuffmanNode**)b;
return node1->freq - node2->freq;
}
void build_huffman_tree(char* s, int n, HuffmanNode** root) {
int freq[MAX_LEN] = {0};
for (int i = 0; i < n; i++) {
freq[s[i]]++;
}
HuffmanNode* nodes[MAX_LEN];
int nodes_size = 0;
for (int i = 0; i < MAX_LEN; i++) {
if (freq[i] > 0) {
nodes[nodes_size] = (HuffmanNode*)malloc(sizeof(HuffmanNode));
nodes[nodes_size]->val = i;
nodes[nodes_size]->freq = freq[i];
nodes[nodes_size]->left = NULL;
nodes[nodes_size]->right = NULL;
nodes_size++;
}
}
while (nodes_size > 1) {
qsort(nodes, nodes_size, sizeof(HuffmanNode*), cmp_node);
HuffmanNode* node1 = nodes[0];
HuffmanNode* node2 = nodes[1];
HuffmanNode* merged_node = (HuffmanNode*)malloc(sizeof(HuffmanNode));
merged_node->val = -1;
merged_node->freq = node1->freq + node2->freq;
merged_node->left = node1;
merged_node->right = node2;
nodes[0] = merged_node;
nodes_size--;
for (int i = 1; i < nodes_size; i++) {
nodes[i] = nodes[i + 1];
}
}
*root = nodes[0];
}
void dfs_huffman_tree(HuffmanNode* root, char* code, int len) {
if (root->val != -1) {
CodeTable ct = {root->val, (char*)malloc((len + 1) * sizeof(char))};
strcpy(ct.code, code);
code_table[code_table_size] = ct;
code_table_size++;
}
if (root->left) {
code[len] = '0';
dfs_huffman_tree(root->left, code, len + 1);
}
if (root->right) {
code[len] = '1';
dfs_huffman_tree(root->right, code, len + 1);
}
}
void build_huffman_code_table(HuffmanNode* root) {
char code[MAX_LEN] = {0};
dfs_huffman_tree(root, code, 0);
}
int get_bit(uint8_t byte, int i) {
return (byte >> (7 - i)) & 1;
}
void compress_file(char* src_file, char* dst_file) {
FILE* fp_src = fopen(src_file, "rb");
if (!fp_src) {
printf("Error: cannot open source file!\n");
return;
}
FILE* fp_dst = fopen(dst_file, "wb");
if (!fp_dst) {
printf("Error: cannot open destination file!\n");
fclose(fp_src);
return;
}
// Count frequency
int freq[MAX_LEN] = {0};
char ch;
while (fread(&ch, sizeof(char), 1, fp_src) == 1) {
freq[ch]++;
}
rewind(fp_src);
// Build Huffman tree
HuffmanNode* root = NULL;
build_huffman_tree(NULL, MAX_LEN, &root);
free_huffman_tree(root);
build_huffman_tree(NULL, MAX_LEN, &root);
// Build Huffman code table
code_table_size = 0;
build_huffman_code_table(root);
// Write Huffman code table to file
fwrite(&code_table_size, sizeof(int), 1, fp_dst);
for (int i = 0; i < code_table_size; i++) {
fwrite(&code_table[i].ch, sizeof(char), 1, fp_dst);
int code_len = strlen(code_table[i].code);
fwrite(&code_len, sizeof(int), 1, fp_dst);
fwrite(code_table[i].code, sizeof(char), code_len, fp_dst);
}
// Compress data and write to file
uint8_t byte = 0;
int bit_count = 0;
while (fread(&ch, sizeof(char), 1, fp_src) == 1) {
char* code = NULL;
for (int i = 0; i < code_table_size; i++) {
if (code_table[i].ch == ch) {
code = code_table[i].code;
break;
}
}
int code_len = strlen(code);
for (int i = 0; i < code_len; i++) {
byte |= (code[i] - '0') << (7 - bit_count);
bit_count++;
if (bit_count == 8) {
fwrite(&byte, sizeof(uint8_t), 1, fp_dst);
byte = 0;
bit_count = 0;
}
}
}
if (bit_count > 0) {
fwrite(&byte, sizeof(uint8_t), 1, fp_dst);
}
fclose(fp_src);
fclose(fp_dst);
}
void decompress_file(char* src_file, char* dst_file) {
FILE* fp_src = fopen(src_file, "rb");
if (!fp_src) {
printf("Error: cannot open source file!\n");
return;
}
FILE* fp_dst = fopen(dst_file, "wb");
if (!fp_dst) {
printf("Error: cannot open destination file!\n");
fclose(fp_src);
return;
}
// Read Huffman code table from file
fread(&code_table_size, sizeof(int), 1, fp_src);
for (int i = 0; i < code_table_size; i++) {
fread(&code_table[i].ch, sizeof(char), 1, fp_src);
int code_len;
fread(&code_len, sizeof(int), 1, fp_src);
code_table[i].code = (char*)malloc((code_len + 1) * sizeof(char));
fread(code_table[i].code, sizeof(char), code_len, fp_src);
code_table[i].code[code_len] = '\0';
}
// Build Huffman tree
HuffmanNode* root = NULL;
build_huffman_tree(NULL, MAX_LEN, &root);
free_huffman_tree(root);
build_huffman_tree(NULL, MAX_LEN, &root);
// Decompress data and write to file
HuffmanNode* current = root;
uint8_t byte;
while (fread(&byte, sizeof(uint8_t), 1, fp_src) == 1) {
for (int i = 0; i < 8; i++) {
int bit = get_bit(byte, i);
if (bit == 0) {
current = current->left;
} else {
current = current->right;
}
if (current->val != -1) {
fwrite(¤t->val, sizeof(char), 1, fp_dst);
current = root;
}
}
}
fclose(fp_src);
fclose(fp_dst);
}
int main() {
char s[MAX_LEN];
printf("Please input a string:\n");
fgets(s, MAX_LEN, stdin);
int n = strlen(s);
if (s[n - 1] == '\n') {
s[n - 1] = '\0';
n--;
}
// Build Huffman tree
HuffmanNode* root = NULL;
build_huffman_tree(s, n, &root);
// Build Huffman code table
code_table_size = 0;
build_huffman_code_table(root);
print_code_table();
// Compress data and write to file
compress_file("input.txt", "output.bin");
// Decompress data and write to file
decompress_file("output.bin", "output.txt");
free_huffman_tree(root);
return 0;
}
```
阅读全文