提供完整的C语言代码
时间: 2023-07-09 19:11:25 浏览: 69
以下是一个简单的C语言实现:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHAR 256
struct node {
char c;
int freq;
struct node *left;
struct node *right;
};
struct code {
char c;
char *bits;
};
struct huffman_tree {
struct node *root;
struct code *table;
};
void freq_count(char *str, int *freq) {
int i;
for (i = 0; i < strlen(str); i++) {
freq[(int)str[i]]++;
}
}
void sort_nodes(struct node **nodes, int n) {
int i, j;
struct node *temp;
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - 1 - i; j++) {
if (nodes[j]->freq > nodes[j+1]->freq) {
temp = nodes[j];
nodes[j] = nodes[j+1];
nodes[j+1] = temp;
}
}
}
}
struct node *build_tree(int *freq) {
int i, n = 0;
struct node **nodes = (struct node **)malloc(sizeof(struct node *) * MAX_CHAR);
for (i = 0; i < MAX_CHAR; i++) {
if (freq[i] > 0) {
nodes[n] = (struct node *)malloc(sizeof(struct node));
nodes[n]->c = (char)i;
nodes[n]->freq = freq[i];
nodes[n]->left = NULL;
nodes[n]->right = NULL;
n++;
}
}
while (n > 1) {
sort_nodes(nodes, n);
struct node *new_node = (struct node *)malloc(sizeof(struct node));
new_node->c = '\0';
new_node->freq = nodes[0]->freq + nodes[1]->freq;
new_node->left = nodes[0];
new_node->right = nodes[1];
nodes[0] = new_node;
for (i = 1; i < n - 1; i++) {
nodes[i] = nodes[i+1];
}
n--;
}
return nodes[0];
}
void build_code_table(struct node *node, char *bits, int depth, struct code *table, int *table_size) {
if (node->left == NULL && node->right == NULL) {
table[*table_size].c = node->c;
table[*table_size].bits = (char *)malloc(sizeof(char) * (depth + 1));
strcpy(table[*table_size].bits, bits);
(*table_size)++;
} else {
char *left_bits = (char *)malloc(sizeof(char) * (depth + 2));
strcpy(left_bits, bits);
strcat(left_bits, "0");
build_code_table(node->left, left_bits, depth+1, table, table_size);
char *right_bits = (char *)malloc(sizeof(char) * (depth + 2));
strcpy(right_bits, bits);
strcat(right_bits, "1");
build_code_table(node->right, right_bits, depth+1, table, table_size);
}
}
struct huffman_tree *build_huffman_tree(char *str) {
int freq[MAX_CHAR] = {0};
freq_count(str, freq);
struct huffman_tree *tree = (struct huffman_tree *)malloc(sizeof(struct huffman_tree));
tree->root = build_tree(freq);
tree->table = (struct code *)malloc(sizeof(struct code) * MAX_CHAR);
int table_size = 0;
build_code_table(tree->root, "", 0, tree->table, &table_size);
return tree;
}
void encode(struct huffman_tree *tree, char *str, char *filename) {
FILE *fout = fopen(filename, "wb");
int i, j, n = strlen(str), bit_count = 0;
char *bits = (char *)malloc(sizeof(char) * (n * MAX_CHAR + 1));
for (i = 0; i < n; i++) {
for (j = 0; j < MAX_CHAR; j++) {
if (tree->table[j].c == str[i]) {
strcat(bits, tree->table[j].bits);
bit_count += strlen(tree->table[j].bits);
break;
}
}
}
fwrite(&bit_count, sizeof(int), 1, fout);
int byte_count = bit_count / 8 + (bit_count % 8 == 0 ? 0 : 1);
char *bytes = (char *)malloc(sizeof(char) * (byte_count + 1));
for (i = 0; i < byte_count; i++) {
bytes[i] = 0;
for (j = 0; j < 8; j++) {
if (bits[i*8+j] == '1') {
bytes[i] |= (1 << (7-j));
}
}
}
fwrite(bytes, sizeof(char), byte_count, fout);
fclose(fout);
}
void decode(struct huffman_tree *tree, char *filename) {
FILE *fin = fopen(filename, "rb");
int bit_count, i, j, byte_count;
fread(&bit_count, sizeof(int), 1, fin);
byte_count = bit_count / 8 + (bit_count % 8 == 0 ? 0 : 1);
char *bytes = (char *)malloc(sizeof(char) * (byte_count + 1));
fread(bytes, sizeof(char), byte_count, fin);
char *bits = (char *)malloc(sizeof(char) * (bit_count + 1));
for (i = 0; i < byte_count; i++) {
for (j = 0; j < 8 && i*8+j < bit_count; j++) {
bits[i*8+j] = (bytes[i] & (1 << (7-j))) ? '1' : '0';
}
}
bits[bit_count] = '\0';
fclose(fin);
struct node *node = tree->root;
for (i = 0; i < bit_count; i++) {
if (bits[i] == '0') {
node = node->left;
} else {
node = node->right;
}
if (node->left == NULL && node->right == NULL) {
printf("%c", node->c);
node = tree->root;
}
}
}
int main() {
char str[100];
printf("Enter a string: ");
scanf("%s", str);
struct huffman_tree *tree = build_huffman_tree(str);
encode(tree, str, "compressed.bin");
decode(tree, "compressed.bin");
return 0;
}
```
请注意,这个实现仅供参考,可能存在错误和不足之处。另外,由于输入的字符串可能包含空格和其他特殊字符,因此在实际应用中需要进行适当的处理。
阅读全文