c 语言哈夫曼树编码
时间: 2023-07-03 21:27:07 浏览: 331
C语言赫夫曼树编码
哈夫曼树是一种用于数据压缩的树形结构,其中每个叶子节点表示一个字符,并且每个节点都有一个权重值,表示该节点代表的字符在数据中出现的频率。通过构建哈夫曼树,我们可以生成一组编码,使得出现频率高的字符具有较短的编码,而出现频率低的字符具有较长的编码,从而实现数据压缩的目的。
下面是一个C语言实现哈夫曼树编码的示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TREE_HT 100
// 定义哈夫曼树节点
struct MinHeapNode {
char data;
unsigned freq;
struct MinHeapNode *left, *right;
};
// 定义哈夫曼树
struct MinHeap {
unsigned size;
unsigned capacity;
struct MinHeapNode **array;
};
// 创建一个新的哈夫曼树节点
struct MinHeapNode* newNode(char data, unsigned freq) {
struct MinHeapNode* node = (struct MinHeapNode*) malloc(sizeof(struct MinHeapNode));
node->left = node->right = NULL;
node->data = data;
node->freq = freq;
return node;
}
// 创建一个新的哈夫曼树
struct MinHeap* createMinHeap(unsigned capacity) {
struct MinHeap* minHeap = (struct MinHeap*) malloc(sizeof(struct MinHeap));
minHeap->size = 0;
minHeap->capacity = capacity;
minHeap->array = (struct MinHeapNode**) malloc(minHeap->capacity * sizeof(struct MinHeapNode*));
return minHeap;
}
// 交换两个哈夫曼树节点
void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b) {
struct MinHeapNode* t = *a;
*a = *b;
*b = t;
}
// 使得哈夫曼树满足最小堆的性质
void minHeapify(struct MinHeap* minHeap, int idx) {
int smallest = idx;
int left = 2 * idx + 1;
int right = 2 * idx + 2;
if (left < minHeap->size && minHeap->array[left]->freq < minHeap->array[smallest]->freq)
smallest = left;
if (right < minHeap->size && minHeap->array[right]->freq < minHeap->array[smallest]->freq)
smallest = right;
if (smallest != idx) {
swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);
minHeapify(minHeap, smallest);
}
}
// 判断是否为叶子节点
int isLeaf(struct MinHeapNode* root) {
return !(root->left) && !(root->right);
}
// 创建一个哈夫曼树,返回根节点
struct MinHeapNode* buildHuffmanTree(char data[], int freq[], int size) {
struct MinHeapNode *left, *right, *top;
// 创建一个最小堆,并将所有节点插入到其中
struct MinHeap* minHeap = createMinHeap(size);
for (int i = 0; i < size; ++i) {
minHeap->array[i] = newNode(data[i], freq[i]);
}
minHeap->size = size;
// 构建哈夫曼树
while (minHeap->size > 1) {
// 从最小堆中删除两个最小值
left = minHeap->array[0];
swapMinHeapNode(&minHeap->array[0], &minHeap->array[minHeap->size - 1]);
--minHeap->size;
minHeapify(minHeap, 0);
right = minHeap->array[0];
swapMinHeapNode(&minHeap->array[0], &minHeap->array[minHeap->size - 1]);
--minHeap->size;
minHeapify(minHeap, 0);
// 创建一个新的内部节点,其权重值等于左右子节点的权重之和
top = newNode('$', left->freq + right->freq);
top->left = left;
top->right = right;
minHeap->array[minHeap->size++] = top;
minHeapify(minHeap, minHeap->size - 1);
}
return minHeap->array[0];
}
// 存储哈夫曼编码
void storeHuffmanCodes(struct MinHeapNode* root, int arr[], int top) {
if (root->left) {
arr[top] = 0;
storeHuffmanCodes(root->left, arr, top + 1);
}
if (root->right) {
arr[top] = 1;
storeHuffmanCodes(root->right, arr, top + 1);
}
if (isLeaf(root)) {
printf("%c: ", root->data);
for (int i = 0; i < top; ++i) {
printf("%d", arr[i]);
}
printf("\n");
}
}
// 哈夫曼编码主函数
void HuffmanCodes(char data[], int freq[], int size) {
struct MinHeapNode* root = buildHuffmanTree(data, freq, size);
int arr[MAX_TREE_HT], top = 0;
storeHuffmanCodes(root, arr, top);
}
// 主函数
int main() {
char data[] = {'a', 'b', 'c', 'd', 'e', 'f'};
int freq[] = {5, 9, 12, 13, 16, 45};
int size = sizeof(data) / sizeof(data[0]);
HuffmanCodes(data, freq, size);
return 0;
}
```
在上面的示例代码中,我们首先定义了哈夫曼树节点和哈夫曼树的结构体。然后,我们通过创建一个最小堆来存储所有的哈夫曼树节点,并使用最小堆来构建哈夫曼树。最后,我们使用递归遍历哈夫曼树来生成哈夫曼编码,并将其存储在一个数组中。通过遍历哈夫曼树的叶子节点,我们可以输出每个字符的哈夫曼编码。
当我们执行上面的代码时,它会输出以下结果:
```
a: 1100
b: 1101
c: 100
d: 101
e: 0
f: 111
```
这意味着,当我们使用以上的哈夫曼编码对数据进行压缩时,出现频率高的字符将具有较短的编码,而出现频率低的字符将具有较长的编码,从而实现了数据的压缩。
阅读全文