用c语言打开文件,读取文件内容到一个字符串中。 遍历字符串,统计每个字符出现的频率。 根据字符频率构造哈夫曼树,用链表来实现,并给每个字符赋予对应的哈夫曼编码
时间: 2024-02-25 14:54:06 浏览: 172
好的,下面是一个参考代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义哈夫曼树的节点结构体
typedef struct huffman_node {
char data; // 节点存储的字符
int freq; // 节点存储的字符出现的频率
struct huffman_node *left; // 左子节点
struct huffman_node *right; // 右子节点
} huffman_node;
// 定义哈夫曼编码的结构体
typedef struct huffman_code {
char data; // 字符
char *code; // 哈夫曼编码
struct huffman_code *next; // 下一个哈夫曼编码
} huffman_code;
// 统计字符出现的频率
void count_freq(const char *str, int *freq) {
int i, n = strlen(str);
for (i = 0; i < n; i++) {
freq[str[i]]++;
}
}
// 创建哈夫曼树的节点
huffman_node *create_node(char data, int freq) {
huffman_node *node = (huffman_node *)malloc(sizeof(huffman_node));
node->data = data;
node->freq = freq;
node->left = NULL;
node->right = NULL;
return node;
}
// 将节点插入到链表中
void insert_node(huffman_node **head, huffman_node *node) {
if (*head == NULL) {
*head = node;
return;
}
if (node->freq < (*head)->freq) {
node->right = *head;
*head = node;
return;
}
huffman_node *cur = *head;
while (cur->right != NULL && node->freq >= cur->right->freq) {
cur = cur->right;
}
node->right = cur->right;
cur->right = node;
}
// 从链表中删除节点
huffman_node *remove_node(huffman_node **head) {
huffman_node *node = *head;
if (node == NULL) {
return NULL;
}
*head = node->right;
node->right = NULL;
return node;
}
// 创建哈夫曼树
huffman_node *create_huffman_tree(const int *freq) {
huffman_node *head = NULL;
int i;
for (i = 0; i < 256; i++) {
if (freq[i] > 0) {
huffman_node *node = create_node(i, freq[i]);
insert_node(&head, node);
}
}
while (head->right != NULL) {
huffman_node *node1 = remove_node(&head);
huffman_node *node2 = remove_node(&head);
huffman_node *parent = create_node(0, node1->freq + node2->freq);
parent->left = node1;
parent->right = node2;
insert_node(&head, parent);
}
return remove_node(&head);
}
// 递归计算哈夫曼编码
void get_huffman_code(huffman_node *node, char *code, int len, huffman_code **head) {
if (node->left == NULL && node->right == NULL) {
huffman_code *hc = (huffman_code *)malloc(sizeof(huffman_code));
hc->data = node->data;
hc->code = (char *)malloc((len + 1) * sizeof(char));
strncpy(hc->code, code, len);
hc->code[len] = '\0';
hc->next = NULL;
huffman_code *cur = *head;
if (cur == NULL) {
*head = hc;
} else {
while (cur->next != NULL) {
cur = cur->next;
}
cur->next = hc;
}
return;
}
code[len] = '0';
get_huffman_code(node->left, code, len + 1, head);
code[len] = '1';
get_huffman_code(node->right, code, len + 1, head);
}
int main() {
FILE *fp;
char *str;
int freq[256] = {0};
huffman_node *root;
huffman_code *hc_head = NULL;
// 打开文件并读取文件内容到字符串中
fp = fopen("input.txt", "r");
if (fp == NULL) {
printf("Failed to open file.\n");
exit(1);
}
fseek(fp, 0, SEEK_END);
long file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
str = (char *)malloc((file_size + 1) * sizeof(char));
fread(str, sizeof(char), file_size, fp);
str[file_size] = '\0';
fclose(fp);
// 统计字符出现的频率
count_freq(str, freq);
// 创建哈夫曼树
root = create_huffman_tree(freq);
// 计算每个字符的哈夫曼编码
char code[256] = {0};
get_huffman_code(root, code, 0, &hc_head);
// 输出每个字符的哈夫曼编码
huffman_code *cur = hc_head;
while (cur != NULL) {
printf("%c: %s\n", cur->data, cur->code);
cur = cur->next;
}
// 释放内存
free(str);
cur = hc_head;
while (cur != NULL) {
huffman_code *tmp = cur;
cur = cur->next;
free(tmp->code);
free(tmp);
}
return 0;
}
```
上面的代码实现了文件的读取、字符频率的统计、哈夫曼树的构造以及哈夫曼编码的计算。
阅读全文