哈夫曼树又称最优树,是一类带权路径长度最短的路。
哈夫曼树结构:
typedef struct Htree{
int data;//数据域,也可以不要,我这里是用来存放下标
int parent,lchild,rchild;//父亲下标,左右儿子下标
int weight;//权重
}Htree;
typedef struct{
Htree TData[MAXSIZE];//哈夫曼树
int size;//这是该树的大小,n*2
}HFMtree;
思路:(我个人这里用到的是堆栈,思路仁者见仁,智者见智)
1.将权重的集合(数组或其他集合)进行排序。
2.一一入栈,栈顶保证存放的是权重最小的那两个结点。
3.进入循环,将栈顶最小权重的两个结点弹出,弹出之后权重相加得到新结点。
4.新结点入栈。
5.将堆栈排序,栈顶保证存放的是权重最小的那两个结点。
6.重复 3,4,5直到栈为空.
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 1000
/*
哈夫曼树的构建
*/
typedef struct Htree{
int data;
int parent,lchild,rchild;
int weight;
}Htree;
typedef struct{
Htree TData[MAXSIZE];//哈夫曼树
int size;//这是该树的大小,n*2
}HFMtree;
typedef struct{
Htree Array[MAXSIZE];
int top;//堆栈头
}Stack_Array;//顺序表堆栈
void Qsort(int left,int right,int a[]){
if(left>=right){//递归出口
return;
}
int temp=a[left];//做好标兵
int i=left,j=right;
while(i<j){
//从右边开始检查起
while(temp<a[j]&&j>i){
j--;
}
if(temp>=a[j]&&j>i){
int t=a[j];
a[j]=a[i];
a[i]=t;
i++;
}
while(temp>a[i]&&j>i){
i++;
}
if(temp<a[i]&&j>i){
int t=a[i];
a[i]=a[j];
a[j]=t;
j--;
}
}
//出来的时候i=j
a[j]=temp;//在这里左边比他小 右边比他大
Qsort(left,i-1,a);
Qsort(i+1,right,a);
}
void PushStack_Array(Stack_Array *S,Htree value){
//顺序堆栈入栈
S->Array[++S->top]=value;
}
Htree PopStack_Array(Stack_Array *S){
Htree x=S->Array[S->top];
S->top--;
return x;
}
int isEmpty(Stack_Array S){
if(S.top<=-1)return 1;
return 0;
}
void sortS(Stack_Array *S){
//对堆栈进行从大到小排序 (权重)
int i,j,len=S->top+1;
for(i=1;i<len;i++){
for(j=1;j<i;j++){
if(S->Array[j].weight<S->Array[i].weight){
Htree t=S->Array[j];
S->Array[j]=S->Array[i];
S->Array[i]=t;
}
}
}
}
//创建哈夫曼树
void Create(int n,int weight[],HFMtree &HT){
//n是结点数,weight是权重的数组
Qsort(0,n-1,weight);//对权重数组进行从小到大排序
int i,j;
HT.size=n*2;
Stack_Array S;
//初始化权重数组,加入哈夫曼数组
for(i=1;i<=n;i++){
HT.TData[i].data=i;
HT.TData[i].weight=weight[i-1];
HT.TData[i].parent=HT.TData[i].lchild=HT.TData[i].rchild=0;//初始化为0
}
for(i=n;i>=1;i--)PushStack_Array(&S,HT.TData[i]);//从大到小入栈
i=9;
//此时栈顶为最小的两个
while(!isEmpty(S)){//循环至堆栈为空
//先出栈两次,得到两个权值最小的结点
Htree h1,h2,ht;
h1=PopStack_Array(&S);
h2=PopStack_Array(&S);
ht.weight=h1.weight+h2.weight;
ht.lchild=h1.data;ht.rchild=h2.data;//设置左右儿子
ht.data=i;
HT.TData[i++]=ht;//放入哈夫曼树
HT.TData[h1.data].parent=HT.TData[h2.data].parent=ht.data;//把原结点的父亲更新一下
PushStack_Array(&S,ht);//将新结点入栈
sortS(&S);//对堆栈从大到小排序(栈顶最小)
}
}
int main(){
int W[8]={5,29,7,8,14,23,3,11},i;
HFMtree HT;
Create(8,W,HT);
for(i=1;i<16;i++){
printf("下标是:%d 权值是:%d ,父亲是:%d 左儿子是:%d,右儿子是:%d \n",HT.TData[i].data,HT.TData[i].weight,HT.TData[i].parent,HT.TData[i].lchild,HT.TData[i].rchild);
}
return 0;
}