資料結構 哈夫曼樹的建立
實驗4 哈夫曼樹的建立
一、實驗目的
1. 理解哈夫曼樹及其應用。
2. 掌握生成哈夫曼樹的演算法。
二、實驗原理
構造哈夫曼樹就是找帶全路徑長度最短的樹,再根據構造出來的樹找出結點對應的哈夫曼編碼
(1)Select()函式:從無雙親的結點中選出權值最小的一個
實現步驟:先假設一個無雙親的結點k為最小結點,接著遍歷所有無雙親的結點,只要檢查到某個結點的權值比當前結點k的權值更小,就把這個更小的結點設為最小結點k,所以最後得到的K就是最小權值結點
(2)main()函式:
1、輸入合法權值
2、給(2*l-1)個結點初始化
3、運用Select()函式來構造哈夫曼樹
4、根據構造好的哈夫曼樹找到每個葉子結點對應的哈夫曼編碼(從葉子結點到
根節點,每走一步找一個編碼)
三、參考程式
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LEN sizeof(struct HTnode)
int i,l,n,w=0,c,start,a1,a2,f;
struct HTnode {
unsigned int weight;
unsigned int parent,lchild,rchild;
}*p,*HT;
typedef char **Huffmancode;
Huffmancode HC;
char *cd;
//選出當前權值最小的結點
select(){
int k=1,j,flag=0;//k一直記錄當前最小值
while((HT+k)->parent!=0) k++;
for(j=k+1;j<=n;j++,flag=0){
if((HT+j)->parent!=0) flag=1;
if((HT+j)->weight==0) flag=1;
if(!flag) {
if((HT+j)->weight<(HT+k)->weight)
k=j;
}
return(k);
}
}
main(){
printf("\n赫夫曼樹的建立
printf("請輸入權值(葉子)數目:");
scanf("%d",&l);
while(l<1) {printf("輸入錯誤,請重新輸入權值數目:"); scanf("%d",&l); }
if(l==1) printf("\n只有一個權值,無須建立赫夫曼樹!");
else {
n=2*l-1;
HT=(struct HTnode*)malloc((n+1)*LEN);
printf("請按對應順序輸入權值(輸入一權值,鍵入一回車):\n");
for(i=1,p=HT+1;i<=l;++i,++p){//1~l是葉節點,給葉節點輸入權值
scanf("%d",&w);
while(w<=0){printf("權值錯,重新輸入此權值:"); scanf("%d",&w);}
p->weight=w; p->parent=0;
p->lchild=0; p->rchild=0;
}
for(i=l+1;i<=n;++i,++p){//l+1~n為雙親結點初始化
p->weight=0; p->parent=0;
p->lchild=0;
}
//構造哈弗曼樹
for(i=l+1;i<=n;++i){//構造雙親結點,選擇合適的左右結點,構造子二叉樹
//選出當前結點中權值最小的兩個a1,a2,並把這兩個結點的雙親指定為i
a1=select(); (HT+a1)->parent=i;
a2=select(); (HT+a2)->parent=i;
//對應的i的左右孩子設為a1,a2,且權值為兩者之和
(HT+i)->lchild=a1;
(HT+i)->rchild=a2;
(HT+i)->weight=(HT+a1)->weight+(HT+a2)->weight;
}
//為哈弗曼樹編碼
HC=(Huffmancode)malloc((l+1)*sizeof(char *));
cd=(char *)malloc(l*sizeof(char));
*(cd+(l-1))='\0';
//為l個葉子結點找哈弗曼編碼
for(i=1;i<=l;++i){
start=l-1;
for(c=i,f=(HT+i)->parent;f!=0;c=f,f=(HT+f)->parent){//從葉子結點開始找對應編碼,直到從此葉子結點一直找到根節點為止
//左結點為0,右結點為1
if((HT+f)->lchild==c) *(cd+(--start))='0';
else *(cd+(--start))='1';
//把每次得到的一位編碼組合,最後得到此結點的最終編碼
*(HC+i)=(char *)malloc((l-start)*sizeof(char));
strcpy(*(HC+i),(cd+start));
}
}
printf("\n對應的二進位制赫夫曼編碼為:\n");
for(i=1;i<=l;++i)
{printf("%s",*(HC+i));
printf(" ");
}
}
}