/*
哈弗曼树的定义
带权路径长度:设二叉树有n个叶子节点,每个叶子节点带有权值Wk,从根节点到每个椰子节点的长度为Lk
则每个叶子节点的带权路径的长度之和就是每个wk*lk之后加起来
最优二叉树或者哈夫曼树:WPL最小的二叉树
*/
#include <stdio.h>
#include <stdlib.h>
//哈弗曼树的构造——每次把权值最小的两个树合并
#define MAXSIZE 100
typedef struct TreeNode* HuffmanTree;
struct TreeNode
{
int Weight;
HuffmanTree left, right;
};
struct HeapNode
{
HuffmanTree data[MAXSIZE];
int size;
int MaxSize;
};
typedef struct HeapNode* MinHeap;
//堆的实现,建立最小堆
void BuildMinHeap(MinHeap H)
{
int parent, child, temp;
int i;
H->data[0]->Weight = -1;//哨兵
for (i = H->size / 2; i > 0; i--)//从深度倒数第二的位置从后向前走
{
temp = H->data[i]->Weight;
for (parent = i; parent * 2 <= H->size; parent = child)
{
//下面寻找最小的儿子
child = parent * 2;//找到爸爸节点的儿子
if ((child != H->size) && (H->data[child + 1]->Weight < H->data[child]->Weight))
child++;//如果说右儿子比左儿子要小,那么左儿子胜出。因为我们这里建立的是最小堆。
//下面进行替换
if (temp <= H->data[child]->Weight) break;
else
{
H->data[parent]->Weight = H->data[child]->Weight;
}
}
H->data[parent]->Weight = temp;
}
}
//堆的删除最小值操作
HuffmanTree DeleteMin(MinHeap H)
{
int parent, child;
int temp;
//第一步,先把堆的根部拿走
HuffmanTree ans = H->data[H->size--];//将ans的值保存起来
temp = H->data[H->size]->Weight;//将下标最大的那个取出来,放在第一个,准备依次向下寻找,小的就上来,大的就下去
for (parent = 1; parent * 2 <= H->size; parent = child)
{
//下面寻找最小的儿子
child = parent * 2;//找到爸爸节点的儿子
if ((child != H->size) && (H->data[child + 1]->Weight < H->data[child]->Weight))
child++;//如果说右儿子比左儿子要小,那么左儿子胜出。因为我们这里建立的是最小堆。
//下面进行替换
if (temp <= H->data[child]->Weight) break;
else
{
H->data[parent]->Weight = H->data[child]->Weight;
}
}
H->data[parent]->Weight = temp;
return ans;
}
//最小堆的插入.插入一定要从下往上插入
void Insert(HuffmanTree Item,MinHeap H)
{
int i;
H->size++;
for (i = H->size; H->data[i/2]->Weight > Item->Weight; i/=2)//当父亲比插入值大的时候,就一直循环
{
H->data[i]->Weight = H->data[i/2]->Weight;//父亲比插入值要大,那么父亲就要走到下面去
//儿子节点 //父亲的值
}
H->data[i / 2]->Weight = Item->Weight;
}
HuffmanTree Huffman(MinHeap H)
{
HuffmanTree T;//最后返回的是哈夫曼树
int i;
BuildMinHeap(H);//先创建一个堆树
for (i = 1; i < H->size; i++)
{
T = (HuffmanTree)malloc(sizeof(struct TreeNode));
T->left = DeleteMin(H);//从堆树中弹出一个最小的放到T的左边
T->right = DeleteMin(H);//从堆树中弹出一个最小的放到T的右边
T->Weight = T->left->Weight + T->right->Weight;
Insert(T, H);
}
T = DeleteMin(H);
return T;
}
数据结构与C语言实现(五)——树(下):哈夫曼树与哈夫曼编码
最新推荐文章于 2024-08-10 18:21:29 发布