資料結構 15 哈夫曼樹以及哈夫曼編碼的實現

2021-07-10 05:38:51 字數 3362 閱讀 7348

參考書籍:資料結構(c語言版)嚴蔚敏吳偉民編著清華大學出版社

假設有n個權值,試構造一棵含有n個葉子結點的二叉樹,每個葉子節點帶權為wi,則其中帶權路徑長度wpl最小的二叉樹叫做最優二叉樹或者哈夫曼樹

特點:哈夫曼樹中沒有度為1的結點,故由n0 = n2+1以及m= n0+n1+n2,n1=0可推出m=2*n0-1,即一棵有n個葉子節點的哈夫曼樹共有2n-1個節點。

通訊傳送的目標是使總碼長盡可能的短。

變長編碼的原則:

1.使用頻率高的字元用盡可能短的編碼(這樣可以減少資料傳輸量);

2.任一字元的編碼都不能作為另乙個字元編碼的開始部分(這樣就使得在兩個字元的編碼之間不需要新增分隔符號)。這種編碼稱為字首編碼

根據每種字元在電文中出現的次數構造哈夫曼樹,將哈夫曼樹中每個分支結點的左分支標上0,右分支標上1,把從根結點到每個葉子結點的路徑上的標號連線起來,作為葉結點所代表的字元的編碼。這樣得到的編碼稱為哈夫曼編碼

思考為什麼哈夫曼編碼符合變長編碼的原則?哈夫曼樹所構造出的編碼的長度是不是最短的?

哈夫曼樹求得編碼為最優字首碼的原因: 在構造哈夫曼樹的過程中:

1.權值大的在上層,權值小的在下層。滿足出現頻率高的碼長短。

2.樹中沒有一片葉子是另一葉子的祖先,每片葉子對應的編碼就不可能是其它葉子編碼的字首。即上述編碼是二進位制的字首碼。

假設每種字元在電文中出現的次數為wi (出現頻率即為權值),其碼長為li,電文中只有n種字元,則編碼後電文總碼長為

四種字元以及他們的權值:a:30, b:5, c:10, d:20

第一步:構建哈夫曼樹

第二步:為哈夫曼樹的每一條邊編碼

第三步:生成哈夫曼編碼表

哈夫曼樹的儲存結構:採用靜態三叉鍊錶

#include#include#include#define n 4//帶權值的葉子節點數或者是需要編碼的字元數

#define m 2*n-1//n個葉子節點構造的哈夫曼樹有2n-1個結點

#define max 10000

typedef char telemtype;

//靜態三叉鍊錶儲存結構

typedef structhtnode;//, *huffmantree;

typedef htnode huffmantree[m+1];//0號單元不使用

typedef char * huffmancode[n+1];//儲存每個字元的哈夫曼編碼表,是乙個字元指標陣列,每個陣列元素是指向字元指標的指標

//構造哈夫曼樹

void createhuffmantree(huffmantree &ht, int *w, int n)

for(int i=n+1; i <=m; i++)

//開始構建哈夫曼樹,即建立ht的後m-n個結點的過程,直至建立出根節點。用哈夫曼演算法

for(int i = n+1; i <= m; i++)

}

//在ht[1...k]裡選擇parent為0的且權值最小的2結點,其序號分別為s1,s2,parent不為0說明該結點已經參與構造了,故不許再考慮

void select(huffmantree ht, int k, int &s1, int &s2)

} }s1 = tmpi;

tmp = max;

tmpi = 0;

for(int i = 1; i <= k; i++)

} }s2 = tmpi;

}

列印哈夫曼樹

//列印哈夫曼滿樹

void printhuffmantree(huffmantree ht, char ch)else

} printf("\n");

}

為哈夫曼樹的每一條分支編碼,並生成哈夫曼編碼表hc

//為每個字元求解哈夫曼編碼,從葉子到根逆向求解每個字元的哈夫曼編碼

void encodinghuffmancode(huffmantree ht, huffmancode &hc)else

c = f;

f = ht[f].parent;

} hc[i] = (char *)malloc((n-start)*sizeof(char));//每次tmp的後n-start個位置有編碼存在

strcpy(hc[i], &tmp[start]);//將tmp的後n-start個元素分給h[i]指向的的字串

}}

列印哈夫曼編碼表,當編碼表生成以後,以後就可以對字串進行編碼了,只要對應編碼表進行轉換即可

//列印哈夫曼編碼表

void printhuffmancoding(huffmancode hc, char ch)

printf("\n");

}

//解碼過程:從哈夫曼樹的根節點出發,按字元'0'或'1'確定找其左孩子或右孩子,直至找到葉子節點即可,便求得該字串相應的字元

void decodinghuffmancode(huffmantree ht, char *ch, char testdecodingstr, int len, char *result){

int p = m;//ht的最後乙個節點是根節點,前n個節點是葉子節點

int i = 0;//指示測試串中的第i個字元

//char result[30];//儲存解碼以後的字串

int j = 0;//指示結果串中的第j個字元

資料結構 哈夫曼樹 哈夫曼編碼

哈夫曼樹又稱最優樹 二叉樹 是一類帶權路徑最短的樹。構造這種樹的演算法最早是由哈夫曼 huffman 1952年提出,這種樹在資訊檢索中很有用。結點之間的路徑長度 從乙個結點到另乙個結點之間的分支數目。樹的路徑長度 從樹的根到樹中每乙個結點的路徑長度之和。結點的帶權路徑長度 從該結點到樹根之間的路徑...

哈夫曼編碼 哈夫曼樹 (資料結構)

哈夫曼編碼,又稱霍夫曼編碼,是一種編碼方式,哈夫曼編碼是可變字長編碼 vlc 的一種。huffman於1952年提出一種編碼方法,該方法完全依據字元出現概率來構造異字頭的平均長度最短的碼字,有時稱之為最佳編碼,一般就叫做huffman編碼 有時也稱為霍夫曼編碼 include include inc...

資料結構 哈夫曼樹與哈夫曼編碼

1 路徑 由乙個結點到另乙個結點之間的所有分支共同構成。2 路徑長度 結點之間的分支數目。3 樹的路徑長度 從樹的根結點到其他所有結點的路徑長度之和。4 權 賦予某一實體的值。在資料結構中,實體包括結點和邊,所以對應有結點權和邊權。5 結點的帶權路徑長度 結點與樹的根結點之間的路徑長度與結點權的乘積...