概念
- 路径长度:从树中一个节点到另一个节点之间的分支构成两个节点之间的路径,路径上分支的数目称为路径长度.
- 树的路径长度:从树根到每一节点的路径长度之和
这个树的路径长度就是16 - 节点的带权路径长度: 从该节点到树根之间的路径长度与节点上权的乘积
- 树的带权路径长度(WPL): 树的每个叶子节点的带权路径之和
以上图为例
这棵树的WPL就是3*5+15*3+40*2+30*2+10*2 = 220
而另一种结构的树的路径长度却如此大,显然总的查找效率没有上一个高
- WPL最小的二叉树称为哈夫曼树(最优二叉树)
- 哈夫曼树算法:
根据给定的n个权值{ Wl,W2...Wn }构成n棵二叉树的集合F={ T1,T2...Tn }, 其中每棵二叉树T:中只有一个带权为W的根结点,其左右子树均为空.
在F中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且新的二叉树的根结点的权值为其左右子树上根结点的权值之和.
在F中删除这两棵树,同时将新得到的二叉树加入F中。
重复2和3步骤,直到F只含一棵树为止。这棵树便是哈夫曼树。
所以我们可以采用最小堆的方法来构建哈夫曼树
结构体
typedef int DataType; //权重类型
typedef struct HuffmanNode
{
DataType wight; //权重
struct HuffmanNode *left,*right; //左右孩子
} HNode; //哈夫曼树节点的结构体
typedef struct HuffmanList
{
HNode** data; //存树头指针的数组
int nowsize,maxsize; //目前节点数和最大值
} HList; //存放树节点的最小堆结构体
构建空堆
//创建空堆
HList* CreatHeap()
{
HList* H = (HList*)malloc(sizeof(HList));
H->data = (HNode**)malloc(sizeof(HNode*)*(MAXSIZE+1));//开辟数组空间
H->nowsize = 0;
H->maxsize = MAXSIZE;
H->data[0] = (HNode*)malloc(sizeof(HNode));
H->data[0]->wight = MINDATA; //哨兵节点
return H;
}
判空判满
int IsFull(HList *H)//判满
{
return H->nowsize==H->maxsize;
}
int IsEmpty(HList *H)//判空
{
return H->nowsize == 0;
}
向下调整以及构建最小堆
void Swap(HList *H,int a,int b)//交换H中两个节点
{
HNode* temp = H->data[a];
H->data[a] = H->data[b];
H->data[b] = temp;
}
void SiftDown(HList* H,int num,int size)//单个节点向下调整
{
int t,flag = 0;
while(num*2 <= size && flag == 0)
{
t = H->data[num]->wight<H->data[num*2]->wight?num:num*2;
if(num*2+1<=size)
t = H->data[t]->wight<H->data[num*2+1]->wight?t:num*2+1;
if(num == t)
flag = 1;
else
Swap(H,num,t);
num = t;
}
}
void MinHeap(HList* H)//构建最小堆