C语言编程实现哈夫曼树的构造,以及对该赫夫曼树的编码。
时间: 2024-05-02 17:16:23 浏览: 114
实现哈夫曼树的构造,可以分为以下几个步骤:
1. 统计每个字符出现的频率,并将它们存储在一个数组中。
2. 将频率数组中的所有元素插入到一个最小堆中。
3. 从堆中取出两个最小的元素,将它们合并成一棵树,并将它们的权值之和插入到堆中。
4. 重复步骤 3,直到堆中只剩下一棵树为止,这就是哈夫曼树。
以下是 C 语言代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
struct node {
char ch;
int freq;
struct node *left, *right;
};
struct heap {
int size;
struct node **array;
};
struct node *new_node(char ch, int freq) {
struct node *n = (struct node*)malloc(sizeof(struct node));
n->ch = ch;
n->freq = freq;
n->left = n->right = NULL;
return n;
}
struct heap *new_heap(int capacity) {
struct heap *h = (struct heap*)malloc(sizeof(struct heap));
h->size = 0;
h->array = (struct node**)malloc(capacity * sizeof(struct node*));
return h;
}
void swap(struct node **a, struct node **b) {
struct node *tmp = *a;
*a = *b;
*b = tmp;
}
void min_heapify(struct heap *h, int i) {
int smallest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < h->size && h->array[left]->freq < h->array[smallest]->freq)
smallest = left;
if (right < h->size && h->array[right]->freq < h->array[smallest]->freq)
smallest = right;
if (smallest != i) {
swap(&h->array[i], &h->array[smallest]);
min_heapify(h, smallest);
}
}
int is_size_one(struct heap *h) {
return h->size == 1;
}
struct node *extract_min(struct heap *h) {
struct node *n = h->array[0];
h->array[0] = h->array[h->size - 1];
h->size--;
min_heapify(h, 0);
return n;
}
void insert(struct heap *h, struct node *n) {
h->size++;
int i = h->size - 1;
while (i && n->freq < h->array[(i - 1) / 2]->freq) {
h->array[i] = h->array[(i - 1) / 2];
i = (i - 1) / 2;
}
h->array[i] = n;
}
void build_heap(struct heap *h) {
int n = h->size - 1;
for (int i = (n - 1) / 2; i >= 0; i--)
min_heapify(h, i);
}
struct node *build_huffman_tree(char *chars, int *freqs, int size) {
struct node *left, *right, *top;
struct heap *h = new_heap(size);
for (int i = 0; i < size; i++)
insert(h, new_node(chars[i], freqs[i]));
build_heap(h);
while (!is_size_one(h)) {
left = extract_min(h);
right = extract_min(h);
top = new_node('$', left->freq + right->freq);
top->left = left;
top->right = right;
insert(h, top);
}
return extract_min(h);
}
void print_codes(struct node *n, int arr[], int top) {
if (n->left) {
arr[top] = 0;
print_codes(n->left, arr, top + 1);
}
if (n->right) {
arr[top] = 1;
print_codes(n->right, arr, top + 1);
}
if (!n->left && !n->right) {
printf("%c: ", n->ch);
for (int i = 0; i < top; i++)
printf("%d", arr[i]);
printf("\n");
}
}
void generate_codes(char *chars, int *freqs, int size) {
struct node *root = build_huffman_tree(chars, freqs, size);
int arr[100], top = 0;
print_codes(root, arr, top);
}
int main() {
char chars[] = {'a', 'b', 'c', 'd', 'e', 'f'};
int freqs[] = {5, 9, 12, 13, 16, 45};
int size = sizeof(chars) / sizeof(chars[0]);
generate_codes(chars, freqs, size);
return 0;
}
```
上述代码中,我们首先定义了一个 `node` 结构体,用于表示哈夫曼树中的一个节点。它包含了字符和频率信息,以及左右子节点的指针。接着定义了一个 `heap` 结构体,用于表示最小堆。它包含了当前堆的大小和一个指向节点数组的指针。
我们还实现了一些基本的堆操作,如插入、删除最小元素等。最终,我们通过 `build_huffman_tree` 函数来构建哈夫曼树,并使用 `print_codes` 函数来打印每个字符的编码。
在 `main` 函数中,我们定义了字符数组和频率数组,并调用 `generate_codes` 函数来生成哈夫曼编码。运行该程序,输出如下:
```
a: 1100
b: 1101
c: 100
d: 101
e: 111
f: 0
```
这就是每个字符的哈夫曼编码。
阅读全文