赫夫曼樹:
赫夫曼樹的原理和構建:
赫夫曼樹又稱為最優樹,是一類帶權路徑長度最短的樹。
最優二叉樹(赫夫曼樹):
路徑:乙個樹結點到另乙個結點之間的分支構成了路徑。
路徑長度:分支的數目。
樹的路徑長度:從樹根到每一結點的路徑長度之和。
樹的帶權路徑長度:樹的所有葉子結點的帶權路徑長度之和。通常記作wpl
結點的帶權路徑長度:該結點到樹根之間的路徑長度與結點上的權的乘積。
這個數的帶權路徑長度:wpl=7 * 1 + 5 * 2 + 2 * 3 + 4 * 3
假設有n個權值,構造一棵有n個葉子結點的二叉樹,每個葉子結點帶權為wi。
其中帶權路徑長度wpl最小的二叉樹稱做最優二叉樹或赫夫曼樹。
如何構造赫夫曼樹?
赫夫曼給出乙個帶有一般規律的演算法,俗稱赫夫曼演算法。
構造方法:
給定n個權值分別為w1, w2, ..., wn的節點。構造赫夫曼樹的演算法描述如下:
1)將這n個結點分別作為n棵樹僅含乙個結點的二叉樹,構成森林f.
2)構造乙個新節點,並從f中選取兩棵根結點權值最小的樹作為新節點的左、右子樹,並且將新節點的權值置為左、右子樹上根結點的權
值之和。
3)從f中刪除剛才選出的兩棵樹,同時將新得到的樹加入f中。
4)重複步驟2和3,直至f中只剩下一棵樹為止。
赫夫曼編碼
赫夫曼編碼是一種被廣泛應用而且非常有效的資料壓縮編碼,它是可變長度編碼。可變長編碼即可以對待處理字串中不同字元使用不等長的二進位制位表示,可變長編碼比固定長度編碼好很多,可以對頻率高的字元賦予短編碼,而對頻率較低的字元則賦予較長一些的編碼,從而可以使平均編碼長度減短,起到壓縮資料的效果。
赫夫曼編碼是字首編碼。如果沒有乙個編碼是另乙個編碼的字首,則稱這樣的編碼為字首編碼。對字首編碼的解碼也是相對簡單的,因為沒有乙個碼是另乙個編碼的字首,所以可以識別出第乙個
編碼,將它翻譯為原碼,再對餘下的編碼檔案重複同樣操作。
赫夫曼編碼首先要構造一棵赫夫曼樹,首先,將每個出現的字元當做乙個獨立的結點,其權值作為它出現的頻度(或次數),然後構造哈夫曼樹。顯然所有字元節點均出現在葉子結點中。我們可以將字元的編碼解釋為從根至該字元路徑上標記的序列,其中標記為0表示"轉向左孩子",標記為1表示為"轉向右孩子"。 如下圖,矩形方塊表示字元及出現的次數
赫夫曼編碼就是讓那些高頻使用的詞彙用更短的編碼來實現,以達到根據使用頻率來有效壓縮資料的目的,這樣的編碼更高效。
赫夫曼編碼是字首編碼。即沒有乙個編碼是另乙個編碼的字首。
赫夫曼編碼的儲存表示及赫夫曼演算法:
1 typedef struct這個赫夫曼演算法由huffmancoding()函式實現;htnode, *huffmantree; //
動態分配陣列儲存赫夫曼樹
56 typedef char * *huffmancode; //
動態分配陣列儲存赫夫曼編碼表78
//赫夫曼演算法
9void huffmancoding(huffmantree &ht, huffmancode &hc,int * w, int
n)10;19
}20for(;i<=m;++i, ++p)21;
23}24//
構建赫夫曼樹
25for(i = n+1; i<=m; ++i)
2635
36 hf = (huffmancode)malloc((n+1)*sizeof(char *));//
分配字元編碼的頭指標向量
37 cd = (char *)malloc(n * sizeof(char)); //
分配求編碼的臨時工作空間
38 cd[n-1] = '\0'
; 39
for(i=1; i<=n; ++i) //
逐個字元求赫夫曼編碼
4048
free
(cd);
49 }//
hufmancoding
我們要對n個字元編碼;
例如a b c d,編碼成相應的赫夫曼編碼;但是要提供這四個字元的權重。
函式的引數介紹:
huffmantree &ht //給定乙個赫夫曼樹的結點
huffmancode &hc //輸出的赫夫曼編碼陣列,字元陣列
int * w //表示n個字元的權重,用int陣列
int n //表示有n個字元
函式的工作內容:
1、 進行分配足夠多的結點,並進行結點初始化;
2、將結點構成赫夫曼樹;
3、進行赫夫曼編碼;
結合下面的圖理解39行到47行**:即赫夫曼編碼的過程
例如:c字元要編碼成1110。
先給赫夫曼編碼的每個數字編個號:
c1=1,c2=1,c3=1, c4 =0;
赫夫曼演算法的原理是會對字元進行從葉子節點到根的方式逆向求編碼;
求c4 :這裡會看到c結點屬於其父節點cf1的左孩子,所以可知c4=0;然後看到cf1還有父結點,繼續向上走;
//當然逆向求得時候是不知道自己最終編碼成幾個數字的,終止條件就是遍歷到根為止。也就是說這裡c4是為了說明方便,一開始是不知道c幾的。
求c3:然後看cf1結點是其父節點cf2的右孩子,所以可知c3=1; 然後看到cf2還有父結點,繼續向上走;
求c2:然後看到cf2結點是其父節點cf3的右孩子,所以可知c2=1; 然後看到cf2還有父結點,繼續向上走;
求c1:然後看到cf3結點是其父節點cf4的右孩子,所以可知c1=1; 這時候cf4沒有父結點了,終止向上遍歷;
就這樣通過遍歷赫夫曼樹的方式對字元的實現了赫夫曼編碼。
資料結構 赫夫曼樹及其應用
赫夫曼 huffman 樹又稱最優樹,是一類帶權路徑長度最短的樹,有著廣泛的應用。1 基本概念 結點路徑 從樹中乙個結點到另乙個結點的之間的分支構成這兩個結點之間的路徑。路徑長度 結點路徑上的分支數目稱為路徑長度。樹的路徑長度 從樹根到每乙個結點的路徑長度之和。結點的帶權路徑長度 從樹的根結點到該結...
赫夫曼樹及其應用
include include includeusing namespace std define n 4 typedef char huffmancode 動態分配陣列儲存赫夫曼編碼表 int wt n n個權值,分別對應a 7 b 5 c 2 d 4 templateclass huffmant...
赫夫曼樹及其應用
首先我們先通過上述示例來構造這棵赫夫曼樹。1 先把有權值的葉子結點按照從小到大的順序排列成乙個有序序列,即a5,e10,b15,d30,c40。2 取頭兩個最小權值的結點作為乙個新結點n1的兩個子結點,注意相對較小的時左孩子,這裡a就是n1的左孩子,e是n1的右孩子,此時新結點的權值就是兩個葉子權值...