哈夫曼樹的應用

2022-02-25 04:53:20 字數 1995 閱讀 3239

期末考試成績出來了,具體分數不公布,只公布等級,a,b,c,d,e

老師要根據具體成績算出每個同學的等級,規則如下

[85, 100]: a;

[70, 85): b;

[60, 70): c;

[0, 60]: d;

完成這種對映,可以用下面這個函式來實現

function

rank(score)

這樣算是完成了,但是結合實際,我們還有乙個條件沒利用上,那就是一張合理的試卷,最後結果應該是大多數人中等,高分和低分的人是比較少的。如果我們把第乙個if語句的條件改為if(score >= 70 && score <85),那麼大多數的成績只要走乙個if,就能夠得出結果,統計全部學生等級的時間就會減少。其實,這是一棵普通樹轉為哈夫曼數的過程。

一開始的程式,如果看成一棵樹,那麼是這樣子的。

而後來的樹,是這樣子的

那麼如何畫出第二棵樹,即如何決定哪個判定條件在上面呢?光憑感覺還不行,要有實際的資料去支援。

遵從乙個原則,讓數量越多的結果,走越短的路,比如說等級b,中等成績的學生數量是比較多的,所以我們希望它能在樹的上方。

下面是步驟

首先要知道每個結果的比重,每個結果是乙個葉子節點。

把葉子節點按照公升序排列,取出前兩個,構造成一棵新的樹,孩子節點就是剛才取出的兩個,樹根節點的比重是孩子節點比重之和,用這個新的根節點取代剛才的兩個孩子節點,與剩下的節點公升序排列,重複直到沒有葉子節點。

上面這個例子其實還不是哈夫曼樹的最佳應用,把原先的樹轉化為哈夫曼樹,是有缺點的,雖然走的分支少了,但是判定條件變複雜了。

還有另外的應用,為利用哈夫曼樹把字元編碼為二進位制。

假設一篇文章裡只有abcdefgh這八個字母,為了傳輸這篇文章,要把它轉化為二進位制。

容易想到,八個字母,是2的3次方,用三位二進位制數就可以表示這八個字母了,而解析的時候,只要按照每3位去解析,就可以還原了。按照這種編碼方式(以下稱為等長編碼),這篇文章編碼後的總長度會變為原來字母數量的3倍。要知道,長度越長,傳輸時間就越長,有沒有辦法去減少編碼後的總長度呢?試想一下一種稍微極端的情況,如果這篇文章中,字母a佔據了大多數,如果按照剛才的方法,那麼總長度還是不變,如果換一種方法,用0表示a,其他的還是三位,那麼顯然總長度會變小,把這種想法具體化,就是哈夫曼樹了。先統計好每個字母出現的次數,算出每個字母的比重,然後構造哈夫曼樹。對每個分支,都左邊的設定為0,右邊的設定為1,從根結點到葉子節點,走過的分支編號序列,就是該節點對應字元的編碼了。假設統計出來的結果是

a: 40%,b: 20%,c: 10%,d: 10%;e: 5%f:5%;g: 5%h: 5%

那麼構造出來的哈夫曼樹是這樣子的(結果不唯一)

各個字元的編碼(編碼表)

a:0b:100

c:1010

d:1011

e: 1100

f: 1101

g:1110

h: 1111

如果總共有100個字母,那麼用一開始的等長編碼方式,長度是300

用哈夫曼編碼,最後的長度是 40*1 + 20*3 + 10 * 4 + 10 * 4 + (5 * 4)*4 = 260

(300 - 260)/300 = 0.1333 即便是後面的一些字母用4位,最後的長度還是比原來減少了13%。

字母的編碼長度不同,如何去解析呢?實際上,這種編碼是字首碼,從左到右掃瞄編碼後的字串,如果是0,那麼該字元就是a,如果是1,那麼得繼續,直到得到乙個在編碼表中的編碼。

結語要充分地去發掘資料隱含的資訊,等長編碼的方法因為沒有利用字元百分比的資訊,所以效果不如哈夫曼編碼

參考:大話資料結構

哈夫曼樹的應用 哈夫曼編碼

include include include 樹結點定義 typedef struct htnode,huffmantree static char n 100 用於儲存正文 哈弗曼編碼,char型二級指標 typedef char huffmancode 封裝最小權結點和次小權結點 typede...

哈夫曼樹的應用

priority queueq 預設構造大頂堆 priority queue,greater q 將元素x放入堆q中q.push x 取出堆頂元素int a q.top 取出堆頂元素,即最小的元素儲存在a中。注 使用堆之前需要引入標準模板庫 include。include include inclu...

哈夫曼編碼 哈夫曼樹

1.定義 哈夫曼編碼主要用於資料壓縮。哈夫曼編碼是一種可變長編碼。該編碼將出現頻率高的字元,使用短編碼 將出現頻率低的字元,使用長編碼。變長編碼的主要問題是,必須實現非字首編碼,即在乙個字符集中,任何乙個字元的編碼都不是另乙個字元編碼的字首。如 0 10就是非字首編碼,而0 01不是非字首編碼。2....