什么是哈夫曼樹
當用 n 個結點(都做葉子結點且都有各自的權值)試圖構建一棵樹時,如果構建的這棵樹的帶權路徑長度最小,稱這棵樹為“最優二叉樹”,有時也叫“赫夫曼樹”或者“哈夫曼樹”。
在構建哈弗曼樹時,要使樹的帶權路徑長度最小,只需要遵循一個原則,那就是:權重越大的結點離樹根越近。在圖 1 中,因為結點 a 的權值最大,所以理應直接作為根結點的孩子結點。
#include<stdio.h> #include<stdlib.h> #include<conio.h> #include<string.h> #include<limits.h> typedef struct{ unsigned int weight; unsigned int parent,lchild,rchild; }htnode,*huffmantree; // 赫夫曼樹的結構類型 typedef char **huffmancode; int min(huffmantree t, int i){ int j,flag; unsigned int k=UINT_MAX; for(j=1;j<=i;j++){ if(t[j].weight<k&&t[j].parent==0){ k=t[j].weight; flag=j; } } t[flag].parent=1; return flag; } void select(huffmantree t,int i,int &s1,int &s2){ int j; s1=min(t,i); s2=min(t,i); if(s1>s2){ j=s1; s1=s2; s2=j; } } void huffmancoding(huffmantree &ht,huffmancode &hc,int *w,int n){ int m,i,s1,s2,start; unsigned int c,f; huffmantree p; char *cd=NULL; m=2*n-1; ht=(huffmantree)malloc((m+1)*sizeof(htnode)); // m+1表示0號單元不用 for(p=ht+1,i=1;i<=n;i++,p++){ p->weight=w[i-1]; p->parent=0; p->lchild=0; p->rchild=0; } for(;i<=m;i++,p++){ p->parent=0; } for(i=n+1;i<=m;i++){ //建立赫夫曼樹 select(ht,i-1,s1,s2); ht[s1].parent=ht[s2].parent=i; ht[i].lchild=s1; ht[i].rchild=s2; ht[i].weight=ht[s1].weight+ht[s2].weight; } hc=(huffmancode)malloc((n+1)*sizeof(char *)); cd=(char *)malloc(n*sizeof(char)); //用來存儲每個字符的編碼 cd[n-1]='\0'; //編碼結束符 for(i=1;i<=n;i++){ start=n-1; for(c=i,f=ht[i].parent;f!=0;c=f,f=ht[f].parent){ // 一直循環知道最后一個沒有雙親的結點,用f來尋找父母往上走 if(ht[f].lchild==c) cd[--start]='0'; else cd[--start]='1'; //這里分支語句用來判斷在左還是右,編碼0和1 } //n-1位置已經存放了'/0',所以用--start,從n-2存放0,1編碼 hc[i]=(char *)malloc((n-start)*sizeof(char)); strcpy(hc[i],&cd[start]); } free(cd); } int main(){ huffmantree ht=NULL; // 二級指針 huffmancode hc; int *w,n,i; printf("Please input the number of all the node digit:"); scanf("%d",&n); w=(int *)malloc(n*sizeof(int)); printf("Please input the %d node digits:\n",n); for(i=0;i<n;i++){ scanf("%d",w+i); } huffmancoding(ht,hc,w,n); for(i=1;i<=n;i++){ puts(hc[i]);} getch(); }