哈弗曼樹也稱爲最優二叉樹,它是帶權路徑長度最短的樹,權值越大的結點就離根節點越近。(一般在哈弗曼編碼中,權值表示出現的概率,即出現的概率越大,那麼訪問時的路徑就越短)。
構建哈弗曼樹:
將n個權值構造出n棵只有根節點的樹,構成森林。
在森林中選出兩個根結點的權值最小的樹分別做左右孩子合併一棵新樹,且新樹的根結點權值爲左右結點之和。
從森林中刪除選取的兩棵樹,並將構成的新想樹插入到森林中。
構建哈弗曼樹的步驟圖解如下。
代碼實現:
//哈弗曼樹 #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node* lchild; struct Node* rchild; }Node; //創建樹 Node* create_tree(int *a,int n) { Node* root=NULL; //創建動態數組 Node** node_a=(Node**)malloc(n*sizeof(Node*)); int i,j; for(i=0;i<n;i++) { node_a[i]=(Node*)malloc(1*sizeof(Node)); node_a[i]->data=a[i]; node_a[i]->lchild=NULL; node_a[i]->rchild=NULL; } int min1,min2; //尋找最小兩個數 for(i=1;i<n;i++) { min1=-1; for(j=0;j<n;j++) { if(node_a[j]!=NULL && min1==-1) { min1=j; continue; } if(node_a[j]!=NULL) { min2=j; break; } } //開始尋找最小兩個數的下標 for(j=min2;j<n;j++) { if(node_a[j]!=NULL) { if(node_a[j]->data < node_a[min1]->data) { min2=min1; min1=j; continue; } if(node_a[j]->data < node_a[min2]->data) { min2=j; } } } //構建成新樹 root=(Node*)malloc(1*sizeof(Node)); root->data=node_a[min1]->data + node_a[min2]->data; printf("data:%d\n",root->data); root->lchild=node_a[min1]; root->rchild=node_a[min2]; //將原來兩棵樹從森林中去掉,並添加新樹 node_a[min1]=root; node_a[min2]=NULL; } free(node_a); node_a=NULL; return root; } //輸出樹 void print_tree(Node* root) { if(root==NULL) return ; printf("%d\t",root->data); print_tree(root->lchild); print_tree(root->rchild); } int main(int argc, char const *argv[]) { int data[]={6,1,7,2,5}; Node*root=create_tree(data,5); print_tree(root); printf("\n"); return 0; }
說明:以上代碼只是根據數據構建一棵哈弗曼樹,並沒有進行其他操作,沒有實現具體應用,如哈弗曼編碼與解碼。