1. 程式人生 > >HuffmanTree的實現及Huffman編碼

HuffmanTree的實現及Huffman編碼

HuffTree的定義:

假設一共有n個data,第i個data有對應的權值wi。使從根節點到所有data的路徑長度乘以其權值和為最小。符合其條件的樹就是HuffmanTree,也被稱為最優二叉樹。

實現步驟:

  1. 先將n個data建成n個只有一個根節點的數
  2. 然後從n箇中找出兩個最小的data
  3. 將這兩個數合併為一個二叉樹,左孩子為最小值,右孩子為第二小值
  4. 將這個樹的根節點的權值設為原來兩個點的權值之和
  5. 在剩下的n-1個根節點中執行步驟2
  6. 直到只剩下一個根節點,結束迴圈。

下面來講一下HuffmanTree的一個最經典的應用,Huffman編碼。

(以下定義摘自百度百科)
Huffman編碼是一種無字首變字長編碼。解碼時不會混淆。
使用Huffman編碼的前提是知道每一個字母出現的頻率。
在編碼時,字母出現的頻率相當於HuffmanTree中的data的權值。然後從根節點開始,每經過一個左子樹,編碼加一個0。每經過一個右子樹,編碼加一個1。
這樣建樹之後,每一個字母都有自己的唯一編碼,且無重複字首。

HuffmanTree及編碼的實現程式碼:

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=100;
typedef struct {
    int weight;
    int parent,lchild,rchild;
}HafNode;//HuffmanTree的基本定義
typedef struct {
    int weight;
    char data;
    char
code[maxn];//需要被建樹的資訊 }HafCode; void Init(HafCode *h,int &n)//初始化輸入資料 { cout<<"Input The Number"<<endl; cin>>n; cout<<"Input The Character And Weight"<<endl; for(int i=0;i<n;++i) cin>>h[i].data>>h[i].weight; } void select(HafNode *h,int
k,int &s1,int &s2)//選擇兩個最小的值 { int i; for(i=0; i<k && h[i].parent != 0; ++i);//選擇一個父節點為0的根節點 s1 = i; for(i=0; i<k; ++i){ if(h[i].parent==0 && h[i].weight<h[s1].weight) s1 = i; } for(i=0; i<k; ++i){ if(h[i].parent==0 && i!=s1) break; } s2 = i; for(i=0; i<k; ++i){ if(h[i].parent==0 && i!=s1 && h[i].weight<h[s2].weight) s2 = i; } } void Huffman(HafCode *h2,HafNode *h1,int n) { char str[maxn]; int m=2*n-1; for(int i=0;i<m;++i){ if(i<n)//前n個全部是葉子節點, h1[i].weight=h2[i].weight; else//後面的是還沒建成的樹 h1[i].weight==0; h1[i].lchild=h1[i].parent=h1[i].rchild=0; } int s1,s2; for(int i=n;i<m;++i){ select(h1,i,s1,s2); h1[s1].parent=i;//建立二叉樹 h1[s2].parent=i; h1[i].lchild=s1; h1[i].rchild=s2; h1[i].weight=h1[s1].weight+h1[s2].weight; //cout<<h1[s1].weight<<" "<<h1[s2].weight<<endl; } str[n]='\0'; //memset(str,0,sizeof(str)); int l,p; for(int i=0;i<n;++i){//從每個葉子節點開始倒序遍歷 l=n-1;//倒序賦值字串 //cout<<h2[i].data<<endl; for(int k=i,p=h1[k].parent;p;k=p,p=h1[k].parent){//沿著葉子回溯到根節點 if(k==h1[p].lchild) str[l]='0'; else str[l]='1'; // cout<<str[l]; l--; } //cout<<endl; strcpy(h2[i].code,str+l+1); } } int main() { int n; HafCode hc[maxn]; HafNode tree[maxn]; Init(hc,n); Huffman(hc,tree,n); for(int i=0;i<n;++i) cout<<hc[i].data<<" "<<hc[i].code<<endl; return 0; }