用C语言构造哈夫曼树并生成哈夫曼编码
时间: 2023-12-22 15:04:10 浏览: 120
构造哈夫曼树,并生成编码
哈夫曼树是一种特殊的二叉树,它常用于数据压缩和编码。构造哈夫曼树的过程分为两个步骤:
1. 选取最小的两个权值作为左右子节点,生成新的节点作为它们的父节点。
2. 将新节点的权值设置为左右子节点权值之和,并将新节点插入到已排序的权值列表中。
重复以上过程,直到所有的节点都被合并成一个根节点,就构造出了哈夫曼树。
生成哈夫曼编码的过程是,在哈夫曼树上从根节点出发,每当向左分支走时,在编码序列中添加一个0;每当向右分支走时,在编码序列中添加一个1。直到走到叶子节点,就得到了该节点对应的哈夫曼编码。
以下是一个用C语言实现哈夫曼树和编码的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NODES 256
#define MAX_CODE_LEN 256
typedef struct node {
unsigned char c;
int weight;
struct node *left;
struct node *right;
} node;
typedef struct code {
unsigned char c;
char bits[MAX_CODE_LEN];
} code;
int freq[MAX_NODES];
node *nodes[MAX_NODES];
int node_count = 0;
node *new_node(unsigned char c, int weight) {
node *n = malloc(sizeof(node));
n->c = c;
n->weight = weight;
n->left = NULL;
n->right = NULL;
return n;
}
void insert_node(node *n) {
int i;
for (i = node_count; i >= 0; i--) {
if (i == 0 || nodes[i - 1]->weight <= n->weight) {
nodes[i] = n;
node_count++;
break;
}
nodes[i] = nodes[i - 1];
}
}
node *pop_node() {
if (node_count == 0) {
return NULL;
}
node_count--;
return nodes[node_count];
}
node *build_tree() {
while (node_count > 1) {
node *n1 = pop_node();
node *n2 = pop_node();
node *n3 = new_node(0, n1->weight + n2->weight);
n3->left = n1;
n3->right = n2;
insert_node(n3);
}
return nodes[0];
}
void free_tree(node *root) {
if (root == NULL) {
return;
}
free_tree(root->left);
free_tree(root->right);
free(root);
}
void print_code(node *root, code *codes, int depth, char *bits) {
if (root == NULL) {
return;
}
if (root->left == NULL && root->right == NULL) {
codes[root->c].c = root->c;
strncpy(codes[root->c].bits, bits, depth);
return;
}
bits[depth] = '0';
print_code(root->left, codes, depth + 1, bits);
bits[depth] = '1';
print_code(root->right, codes, depth + 1, bits);
}
void print_freq(char *str) {
int i;
printf("Char\tFrequency\n");
for (i = 0; i < strlen(str); i++) {
freq[str[i]]++;
}
for (i = 0; i < MAX_NODES; i++) {
if (freq[i] > 0) {
printf("%c\t%d\n", i, freq[i]);
}
}
}
void print_codes(code *codes) {
int i;
printf("Char\tHuffman Code\n");
for (i = 0; i < MAX_NODES; i++) {
if (codes[i].bits[0] != '\0') {
printf("%c\t%s\n", codes[i].c, codes[i].bits);
}
}
}
int main() {
char str[] = "hello world";
code codes[MAX_NODES] = {0};
node *root;
int i;
print_freq(str);
for (i = 0; i < MAX_NODES; i++) {
if (freq[i] > 0) {
insert_node(new_node(i, freq[i]));
}
}
root = build_tree();
print_code(root, codes, 0, malloc(sizeof(char) * MAX_CODE_LEN));
print_codes(codes);
free_tree(root);
return 0;
}
```
在上面的代码中,我们首先统计了输入字符串中每个字符出现的频率,然后按照频率构造了哈夫曼树,并生成了每个字符对应的哈夫曼编码。最后输出了字符频率和哈夫曼编码的对应关系。
阅读全文