資料結構 2 2 Huffman樹

2022-03-15 02:09:11 字數 3582 閱讀 1249

1.huffman樹是什麼

huffman樹也稱為哈夫曼編碼,是一種編碼方式,常用於協議的制定,以節省傳輸空間。

a - f字母,出現的頻率分別為:

a:5,b: 24, c:7,d:17,e:34,f:5,g:13

對比:

1)使用常規協議

如果我們將這些字母無論大小進行編碼,一共是7個字母,因此協議規定用三位二進位制數表示,傳輸完這105個字元,共需要105*3 = 315位。

2)使用huffman樹

如果我們按照huffman樹的規則(如上圖),共需要 5*4 + 24 * 2 + 7*4 + 17*2 + 34*1+5*5+13*3 = 228位,共節省87位,大約節省27%的頻寬占用。

2.huffman樹的原理

huffman樹是依據字元的出現頻次,對字元進行二進位制的編碼,出現頻次高的節點編碼字元少,出現頻次低的位元組編碼字元多。

感謝:  博主:jiaxin tse

如圖是huffman樹的構建過程,字元的權重為出現頻次。

構建過程:

step1:將權重最小的兩個字元節點構建乙個父節點,權重為兩者權重之和

step1 進行 size - 1次 ,即可完成huffman樹的構建。

編碼過程: 給定字串,以及"單詞-頻次map" ,構建huffman樹,將給定字串轉成二進位制字串

以字元d為例子,從根節點開始,右枝為1,左枝為0,因此d的編碼就是111

給定 abdc  => 0101111100

因為每乙個被編碼的字元節點是葉子節點,因此每一串二進位制編碼都有唯一對應的解碼

解碼過程: 給定二進位制編碼,以及"單詞-頻次map",構建huffman樹,將給定的二進位制字串轉成字串

0101111100 => abdc

3.huffman樹的三大操作

huffman樹常見的三大操作有 構建、編碼、解碼。上面給出了一些基本原理和使用,接下來是**設計的思路。

node 以及tree :

/**

* 哈夫曼樹 */

public

class

huffmantree

static

class

tree

1)構建huffman樹step1: 將每個字元抽象成乙個節點,使用priprotiesqueue這種排序的結構,按照node的權值,也就是單詞的出現頻次為優先順序排序

step2: 取出其中權值最小的兩個節點,進行構建父節點,父節點權值為子節點權值之和

假設初始的節點數(初始的佇列大小)為size,那麼需要size - 1次step2才能完成整顆huffman樹的構建。

記得儲存葉子節點的列表,以便編碼的時候能從葉子節點向根節點進行拼接字串。

/**

* 構建huffman樹

* @return

*/public static tree buildhuffmantree(

mapcharandcounts)

// 進行建樹操作,進行size-1次操作,每次取出兩個最小的權值的節點,構建父節點並合併權值。

for(int i = 0 ; i < charandcounts.size() - 1 ; i++ )

// 經過size-1次合併操作後,佇列中只剩下乙個節點

huffmantree.root = priorityqueue.poll();

return huffmantree;

}

2)編碼 : 給定字串,以及"單詞-頻次map" ,構建huffman樹,將給定字串轉成二進位制字串首先使用 "單詞-頻次"map 構建huffman樹。

依次遍歷每個huffman樹的葉子節點,每個節點由葉子節點向根節點遍歷,並進行 0 、1的拼接。

這樣就生成了 map《字元,二進位制編碼》表。

然後依次遍歷給定字串的每個字元,分別轉成二進位制編碼拼接即可。

/**

* 進行編碼

* @param str

* @param charandcounts

* @return

*/public staticstring encode(

string str,

mapcharandcounts)else if(current.parent != null && current ==current.parent.right)

current =current.parent;

}chandencoding.put(leafnode.ch,binarycode);

}system.out.println(chandencoding);

// 3.遍歷每個字元進行編碼

stringbuffer strencoded = newstringbuffer();

for(charch : str.tochararray())

returnstrencoded.tostring();

}

測試:

public static voidmain(string args) 

結果:

0100110010111

3)解碼:給定二進位制字串,以及"單詞-頻次map「,構建huffman樹,將給定二進位制字串轉成原未經編碼的字串。首先使用"單詞-頻次"map 構建huffman樹。

然後按照給定的二進位制字串,挨個進行從根的查詢,找到葉子節點後就轉成原字元,從下乙個字串索引開始繼續解碼。

/**

* 解碼過程

* @param

binstr

* @param

charsandcounts

* @return

*/public

static

string decode(

string binstr,

mapcharsandcounts)

else

if(ch == '0')

i++;}}

return

originalstr.tostring();

}

測試:

public

static

void

main(string args)

結果:

0100110010111abcd

abcd

資料結構 Huffman樹

參照書上寫的huffman樹的 結構用的是線性儲存的結構 不是二叉鍊錶 裡面要用到查詢最小和第二小 理論上錦標賽法比較好 但是實現好麻煩啊 考慮到資料量不是很大 就直接用比較笨的先找最小 去掉最小再找第二小的方法了。include include include typedef struct htn...

資料結構 Huffman樹

參照書上寫的huffman樹的 結構用的是線性儲存的結構 不是二叉鍊錶 裡面要用到查詢最小和第二小 理論上錦標賽法比較好 但是實現好麻煩啊 考慮到資料量不是很大 就直接用比較笨的先找最小 去掉最小再找第二小的方法了。include include include typedef struct htn...

oj資料結構 Huffman樹

對輸入的英文大寫字母進行統計概率 然後構建哈夫曼樹,輸出是按照概率降序排序輸出huffman編碼。大寫字母個數 n 第乙個字母 第二個字母 第三個字母 第n個字母。字母1 出現次數 huffman編碼 字母2 出現次數 huffman編碼 字母3 出現次數 huffman編碼 字母n 出現次數 hu...