以前學過的知識都沒啥印象了,再次記錄一下。
哈夫曼編碼(huffman coding),又稱霍夫曼編碼,是一種編碼方式,可變字長編碼(vlc)的一種。huffman於2023年提出一種編碼方法,是一種統計編碼方式,屬於無失真壓縮編碼。哈夫曼編碼是變長編碼,對於出現頻率高的資訊,編碼長度較短,出現頻率低的資訊,編碼長度較長。這樣處理全部資訊的總碼長一定小於實際資訊的符號長度。有時稱之為最佳編碼,一般就叫做huffman編碼(有時也稱為霍夫曼編碼)。
哈夫曼編碼,主要目的是根據使用頻率來最大化節省字元(編碼)的儲存空間。
比如我們有一段文字「badcadfeed」,顯然用二進位制數字(0和1)表示是很自然的想法。
這樣真正傳輸的資料就是「001000011010000011101100100011」,對方接收時同樣按照3位一組解碼。如果一篇文章很長,這樣的二進位制串也非常的可怕。而且事實上,每個字母或者漢子的出現頻率是不同的。
假設六個字母的頻率為a 27,b 8, c 15, d 15 , e 30, f 5,合起來正好是100%,那就意味著我們完全可以用哈夫曼樹來規劃它們。
左圖為構造哈夫曼樹的過程的權值顯示。右圖為將權值左分支改為0,右分支改為1後的哈夫曼樹。
我們對這六個字母用其從樹根到葉子所經過的路徑的0或1來編碼,可以得到下表:
也就是說我們的資料被壓縮了,節約了大概17%的儲存或傳輸成本。隨著字元的增加和多字元權重的不同,這種壓縮會更顯出優勢來。
接收到哈夫曼編碼後應該如何解碼呢?
仔細觀察上面的赫夫曼編碼表中各個字母的編碼會發現,不存在容易與1001、1000混淆的10、100等編碼。這就說明若要設計長短不等的編碼,則必須是任一字元的編碼都不是另乙個字元的編碼的字首,這種編碼稱作字首編碼。
可僅僅是這樣不足以讓我們去方便的解碼,因此解碼時,還是要用到哈夫曼樹,即傳送方和接收方必須約定好同樣的哈夫曼編碼規則。
①概率統計(如對一幅影象或者m幅同種型別影象作灰度統計),得到n個不同概率的資訊符號;
②將訊號源的符號按照出現概率遞減的順序排列;
③在信源符號中選擇概率最小的兩個,將他們的概率相加,計算結果作為其合事件(新符號)的出現概率。在合併運算時,概率大的符號用編碼0表示,概率小的符號用編碼1表示;
④這時概率的個數減為n-1個,將這n-1個概率,按從大到小的順序排序;
⑤重複③,將新排序後的最後兩個小概率再相加,計算合事件的概率,如此反覆重複n-1次,只帶概率相加的結果為1為止;
⑥記錄下概率為1處到當前訊號源符號之間的0,1序列,從而得到每個符號的編碼,構成霍夫曼碼字,到此編碼結束。
簡易的理解就是,假如我有a,b,c,d,e五個字元,出現的頻率(即權值)分別為5,4,3,2,1,那麼我們第一步先取兩個最小權值作為左右子樹構造乙個新樹,即取1,2構成新樹,其結點為1+2=3,權重大的符號用1表示,權重小的符號用0表示,如圖:
虛線為新生成的結點,第二步再把新生成的權值為3的結點放到剩下的集合中,所以集合變成,再根據第二步,取最小的兩個權值構成新樹,如圖:
再依次建立哈夫曼樹,如下圖:
其中各個權值替換對應的字元即為下圖:
所以各字元對應的編碼為:a->11,b->10,c->00,d->011,e->010
霍夫曼編碼是一種無字首編碼。解碼時不會混淆。其主要應用在資料壓縮,加密解密等場合。
如果考慮到進一步節省儲存空間,就應該將出現概率大(佔比多)的字元用盡量少的0-1進行編碼,也就是更靠近根(節點少),這也就是最優二叉樹-哈夫曼樹。
哈夫曼樹又稱最優二叉樹,是一種帶權路徑長度最短的二叉樹。所謂樹的帶權路徑長度,就是樹中所有的葉結點的權值乘上其到根結點的路徑長度(若根結點為0層,葉結點到根結點的路徑長度為葉結點的層數)。樹的帶權路徑長度記為wpl=(w1*l1+w2*l2+w3*l3+…+ wn*ln),n個權值wi(i=1,2,…n)構成一棵有n個葉結點的二叉樹,相應的葉結點的路徑長度為li(i=1,2,…n)。可以證明哈夫曼樹的wpl是最小的。
構造哈夫曼樹的演算法如下:
1)對給定的n個權值構成n棵二叉樹的初始集合f=,其中每棵二叉樹ti中只有乙個權值為wi的根結點,它的左右子樹均為空。
2)在f中選取兩棵根結點權值最小的樹作為新構造的二叉樹的左右子樹,新二叉樹的根結點的權值為其左右子樹的根結點的權值之和。
3)從f中刪除這兩棵樹,並把這棵新的二叉樹同樣以公升序排列加入到集合f中。
4)重複2)和3),直到集合f中只有一棵二叉樹為止。
其實赫夫曼樹使用場景還真不少,例如apache負載均衡的按權重請求策略的底層演算法、咱們生活中的路由器的路由演算法、利用哈夫曼樹實現漢字點陣字形的壓縮儲存
參考:
哈夫曼編碼 哈夫曼樹
1.定義 哈夫曼編碼主要用於資料壓縮。哈夫曼編碼是一種可變長編碼。該編碼將出現頻率高的字元,使用短編碼 將出現頻率低的字元,使用長編碼。變長編碼的主要問題是,必須實現非字首編碼,即在乙個字符集中,任何乙個字元的編碼都不是另乙個字元編碼的字首。如 0 10就是非字首編碼,而0 01不是非字首編碼。2....
哈夫曼樹 哈夫曼編碼
定義從a結點到b結點所經過的分支序列為從a結點到b結點的路徑 定義從a結點到b結點所進過的分支個數為從a結點到b結點的路徑長度 從二叉樹的根結點到二叉樹中所有結點的路徑長度紙盒為該二叉樹的路徑長度 huffman樹 帶權值路徑長度最小的擴充二叉樹應是權值大的外界點舉例根結點最近的擴充二叉樹,該樹即為...
哈夫曼編碼 哈夫曼樹
哈夫曼樹是乙個利用權值進行優化編碼的乙個比較奇怪的樹,他的實現比較簡單,用途也比較單一。哈夫曼樹的實現,實現要求 通過哈夫曼樹可以保證在編碼過程中不會出現例如 1000和100這樣的編碼規則,否則就會編碼失敗,因為1000和100在某些情況下的編碼會一模一樣。通過哈夫曼樹可以保證權值大的值進行編碼時...