期末考試成績出來了,具體分數不公布,只公布等級,a,b,c,d,e
老師要根據具體成績算出每個同學的等級,規則如下
[85, 100]: a;
[70, 85): b;
[60, 70): c;
[0, 60]: d;
完成這種對映,可以用下面這個函式來實現
function這樣算是完成了,但是結合實際,我們還有乙個條件沒利用上,那就是一張合理的試卷,最後結果應該是大多數人中等,高分和低分的人是比較少的。如果我們把第乙個if語句的條件改為if(score >= 70 && score <85),那麼大多數的成績只要走乙個if,就能夠得出結果,統計全部學生等級的時間就會減少。其實,這是一棵普通樹轉為哈夫曼數的過程。rank(score)
一開始的程式,如果看成一棵樹,那麼是這樣子的。
而後來的樹,是這樣子的
那麼如何畫出第二棵樹,即如何決定哪個判定條件在上面呢?光憑感覺還不行,要有實際的資料去支援。
遵從乙個原則,讓數量越多的結果,走越短的路,比如說等級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....