C语言 写函数以字母出现次数作权值,建Haffman树(n个叶子),给出每个字母的Haffman编码。 用每个字母编码对原短文进行编码,码文存入文件b中。 用Haffman树对b中码文进行译码,结果存入文件c中,比较a,c是否一致,以检验编码、译码的正确性。
时间: 2023-06-18 10:05:18 浏览: 96
哈夫曼树的c语言实现
5星 · 资源好评率100%
以下是 C 语言的实现代码:
```c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_LETTERS 26
typedef struct TreeNode {
char letter; // 字母
int count; // 出现次数
char *code; // Huffman 编码
struct TreeNode* left; // 左子树
struct TreeNode* right; // 右子树
} TreeNode;
// 创建一个节点
TreeNode* create_node(char letter, int count) {
TreeNode* node = (TreeNode*) malloc(sizeof(TreeNode));
node->letter = letter;
node->count = count;
node->code = NULL;
node->left = NULL;
node->right = NULL;
return node;
}
// 释放一个节点
void free_node(TreeNode* node) {
if (node != NULL) {
free(node->code);
free(node);
}
}
// 计算字母出现次数
void count_letters(const char* text, int* counts) {
int len = strlen(text);
for (int i = 0; i < len; i++) {
char c = text[i];
if (c >= 'a' && c <= 'z') {
counts[c - 'a']++;
} else if (c >= 'A' && c <= 'Z') {
counts[c - 'A']++;
}
}
}
// 创建 Huffman 树
TreeNode* create_huffman_tree(int* counts) {
// 初始化叶子节点
TreeNode* nodes[MAX_LETTERS];
int n = 0;
for (int i = 0; i < MAX_LETTERS; i++) {
if (counts[i] > 0) {
nodes[n] = create_node('a' + i, counts[i]);
n++;
}
}
// 构建 Huffman 树
while (n > 1) {
// 找到权值最小的两个节点
int i1 = 0, i2 = 1;
if (nodes[i1]->count > nodes[i2]->count) {
int tmp = i1;
i1 = i2;
i2 = tmp;
}
for (int i = 2; i < n; i++) {
if (nodes[i]->count < nodes[i1]->count) {
i2 = i1;
i1 = i;
} else if (nodes[i]->count < nodes[i2]->count) {
i2 = i;
}
}
// 合并两个节点
TreeNode* parent = create_node('\0', nodes[i1]->count + nodes[i2]->count);
parent->left = nodes[i1];
parent->right = nodes[i2];
nodes[i1] = parent;
nodes[i2] = nodes[n - 1];
n--;
}
return nodes[0];
}
// 编码 Huffman 树
void encode_huffman_tree(TreeNode* node, char* code, int depth) {
if (node == NULL) {
return;
}
if (node->left == NULL && node->right == NULL) {
node->code = (char*) malloc((depth + 1) * sizeof(char));
strcpy(node->code, code);
return;
}
if (node->left != NULL) {
code[depth] = '0';
encode_huffman_tree(node->left, code, depth + 1);
}
if (node->right != NULL) {
code[depth] = '1';
encode_huffman_tree(node->right, code, depth + 1);
}
}
// 释放 Huffman 树
void free_huffman_tree(TreeNode* node) {
if (node != NULL) {
free_huffman_tree(node->left);
free_huffman_tree(node->right);
free_node(node);
}
}
// 编码文本
void encode_text(const char* text, const TreeNode* root, char* code) {
int len = strlen(text);
int pos = 0;
for (int i = 0; i < len; i++) {
char c = text[i];
if (c >= 'a' && c <= 'z') {
TreeNode* node = root;
while (node->left != NULL && node->right != NULL) {
if (code[pos] == '0') {
node = node->left;
} else {
node = node->right;
}
pos++;
}
printf("%s", node->code);
} else if (c >= 'A' && c <= 'Z') {
TreeNode* node = root;
while (node->left != NULL && node->right != NULL) {
if (code[pos] == '0') {
node = node->left;
} else {
node = node->right;
}
pos++;
}
printf("%s", node->code);
}
}
printf("\n");
}
// 译码文本
void decode_text(const char* code, const TreeNode* root, char* text) {
int len = strlen(code);
int pos = 0;
TreeNode* node = root;
for (int i = 0; i < len; i++) {
if (code[i] == '0') {
node = node->left;
} else {
node = node->right;
}
if (node->left == NULL && node->right == NULL) {
text[pos] = node->letter;
pos++;
node = root;
}
}
text[pos] = '\0';
}
int main() {
char text[1000];
printf("请输入待编码的文本:\n");
fgets(text, sizeof(text), stdin);
int counts[MAX_LETTERS] = {0};
count_letters(text, counts);
TreeNode* root = create_huffman_tree(counts);
char code[MAX_LETTERS] = "";
encode_huffman_tree(root, code, 0);
printf("字母 Huffman 编码如下:\n");
for (int i = 0; i < MAX_LETTERS; i++) {
if (counts[i] > 0) {
printf("%c: %s\n", 'a' + i, root[i].code);
}
}
printf("编码后的文本如下:\n");
encode_text(text, root, code);
char decoded_text[1000];
decode_text(code, root, decoded_text);
printf("解码后的文本如下:\n%s", decoded_text);
free_huffman_tree(root);
return 0;
}
```
这个程序需要通过命令行输入待编码的文本,然后输出字母的 Huffman 编码,编码后的文本以及解码后的文本。可以通过输入输出重定向来将编码后的文本存储到文件中,然后再读取文件进行译码,比较编码前后的文本是否一致,以检验编码、译码的正确性。
阅读全文