漫畫:「哈夫曼編碼」 是什麼鬼?

2020-12-03 CSDN

作者 | 小灰

來源 | 程式設計師小灰(ID:chengxuyuanxiaohui)

在上一期,我們介紹了一種特殊的數據結構 「哈夫曼樹」,也被稱為最優二叉樹。沒看過的小夥伴可以點擊下方連結:

漫畫:什麼是 「哈夫曼樹」 ?

那麼,這種數據結構究竟有什麼用呢?我們今天就來揭曉答案。

計算機系統是如何存儲信息的呢?

計算機不是人,它不認識中文和英文,更不認識圖片和視頻,它唯一「認識」的就是0(低電平)和1(高電平)。

因此,我們在計算機上看到的一切文字、圖像、音頻、視頻,底層都是用二進位來存儲和傳輸的。

從狹義上來講,把人類能看懂的各種信息,轉換成計算機能夠識別的二進位形式,被稱為編碼。

編碼的方式可以有很多種,我們大家最熟悉的編碼方式就屬ASCII碼了。

在ASCII碼當中,把每一個字符表示成特定的8位二進位數,比如:

顯然,ASCII碼是一種等長編碼,也就是任何字符的編碼長度都相等。

為什麼這麼說呢?讓我們來看一個例子:

假如一段信息當中,只有A,B,C,D,E,F這6個字符,如果使用等長編碼,我們可以把每一個字符都設計成長度為3的二進位編碼:

如此一來,給定一段信息 「ABEFCDAED」,就可以編碼成二進位的 「000 001 100 101 010 011 000 100 011」,編碼總長度是27。

但是,這樣的編碼方式是最優的設計嗎?如果我們讓不同的字符對應不同長度的編碼,結果會怎樣呢?比如:

如此一來,給定的信息 「ABEFCDAED」,就可以編碼成二進位的 「0 00 10 11 01 1 0 10 1」,編碼的總長度只有14。

哈夫曼編碼(Huffman Coding),同樣是由麻省理工學院的哈夫曼博所發明,這種編碼方式實現了兩個重要目標:

1.任何一個字符編碼,都不是其他字符編碼的前綴。

2.信息編碼的總長度最小。

哈夫曼編碼的生成過程是什麼樣子呢?讓我們看看下面的例子:

假如一段信息裡只有A,B,C,D,E,F這6個字符,他們出現的次數依次是2次,3次,7次,9次,18次,25次,如何設計對應的編碼呢?

我們不妨把這6個字符當做6個葉子結點,把字符出現次數當做結點的權重,以此來生成一顆哈夫曼樹:

這樣做的意義是什麼呢?

哈夫曼樹的每一個結點包括左、右兩個分支,二進位的每一位有0、1兩種狀態,我們可以把這兩者對應起來,結點的左分支當做0,結點的右分支當做1,會產生什麼樣的結果?

這樣一來,從哈夫曼樹的根結點到每一個葉子結點的路徑,都可以等價為一段二進位編碼:

上述過程藉助哈夫曼樹所生成的二進位編碼,就是哈夫曼編碼。

現在,我們面臨兩個關鍵的問題:

首先,這樣生成的編碼有沒有前綴問題帶來的歧義呢?答案是沒有歧義。

因為每一個字符對應的都是哈夫曼樹的葉子結點,從根結點到這些葉子結點的路徑並沒有包含關係,最終得到的二進位編碼自然也不會是彼此的前綴。

其次,這樣生成的編碼能保證總長度最小嗎?答案是可以保證。

哈夫曼樹的重要特性,就是所有葉子結點的(權重 X 路徑長度)之和最小。

放在信息編碼的場景下,葉子結點的權重對應字符出現的頻次,結點的路徑長度對應字符的編碼長度。

所有字符的(頻次 X 編碼長度)之和最小,自然就說明總的編碼長度最小。

private Node root;private Node[] nodes;//構建哈夫曼樹publicvoidcreateHuffmanTree(int[] weights){//優先隊列,用於輔助構建哈夫曼樹Queue<Node> nodeQueue = new PriorityQueue<>(); nodes = new Node[weights.length];//構建森林,初始化nodes數組for(int i=0; i<weights.length; i++){ nodes[i] = new Node(weights[i]); nodeQueue.add(nodes[i]);}//主循環,當結點隊列只剩一個結點時結束while (nodeQueue.size() > 1) {//從結點隊列選擇權值最小的兩個結點Node left = nodeQueue.poll();Node right = nodeQueue.poll();//創建新結點作為兩結點的父節點Node parent = new Node(left.weight + right.weight, left, right); nodeQueue.add(parent);} root = nodeQueue.poll();}//輸入字符下表,輸出對應的哈夫曼編碼public String convertHuffmanCode(int index){return nodes[index].code;}//用遞歸的方式,填充各個結點的二進位編碼publicvoidencode(Node node, String code){if(node == null){return;} node.code = code; encode(node.lChild, node.code+"0"); encode(node.rChild, node.code+"1");}publicstaticclassNodeimplementsComparable<Node>{int weight;//結點對應的二進位編碼String code;Node lChild;Node rChild;publicNode(int weight){this.weight = weight;}publicNode(int weight, Node lChild, Node rChild){this.weight = weight;this.lChild = lChild;this.rChild = rChild;}@OverridepublicintcompareTo(Node o){returnnew Integer(this.weight).compareTo(new Integer(o.weight));}}publicstaticvoidmain(String[] args){char[] chars = {'A','B','C','D','E','F'};int[] weights = {2,3,7,9,18,25};HuffmanCode huffmanCode = new HuffmanCode(); huffmanCode.createHuffmanTree(weights); huffmanCode.encode(huffmanCode.root, "");for(int i=0; i<chars.length; i++){System.out.println(chars[i] +":" + huffmanCode.convertHuffmanCode(i));}}

這段代碼中,Node類增加了一個新欄位code,用於記錄結點所對應的二進位編碼。

當哈夫曼樹構建之後,就可以通過遞歸的方式,從根結點向下,填充每一個結點的code值。

相關焦點

  • 哈夫曼編碼 :: 如何求出一串字符集各個字符對應的哈夫曼編碼
    只要會構造哈夫曼樹,哈夫曼編碼特別簡單,一眼就能看出來。方法如下:首先看下面題目已知字符集{ a, b, c, d, e, f },若各字符出現的次數分別為{ 6, 3, 8, 2, 10, 4 },則對應字符集中各字符的哈夫曼編碼可能是:A,00, 1011, 01, 1010, 11, 100B,00, 100, 110, 000, 0010
  • 靜態哈夫曼編碼的快速硬體實現
    ,最後先輸出0~9元素對應的編碼,再按照輸入數據順序輸出各數據對應的哈夫曼編碼。  1 系統設計方案  哈夫曼編碼的基本思想是將出現概率較大的數據用較短的編碼表示,而將出現概率較小的數據用較長的編碼表示。通常的做法是先根據輸入數據的頻次構造一棵哈夫曼樹,再通過遍歷樹中的每一個節點來生成葉子節點即輸入數據的哈夫曼編碼。
  • 基於FPGA的快速哈夫曼編碼設計
    碼錶方式將題目與實際應用結合起來,針對不同場景給出不同的碼錶快速編碼;不過考慮到無規律信號的編碼,所以通過靜態編碼使我們的作品更加具有普適性,我們還採用三位範式編碼的方式,縮短輸出周期;同時在數據輸入結束之前開始排序,減少編碼實際佔用的時間。0 引言  哈夫曼編碼是基於帶權路徑最小的最優二叉樹——哈夫曼樹的一種平均碼長最短的編碼方式。
  • 基於verilog實現哈夫曼編碼的新方法
    ,編碼器通過查表的方法輸出哈夫曼編碼[1];編碼器動態生成哈夫曼樹,通過遍歷節點方式獲取哈夫曼編碼[2-3]。配置字符池的同時逐步生成哈夫曼編碼,可以提高硬體利用率,並且無需額外操作來提取哈夫曼編碼。引言  哈夫曼(Huffman)編碼對出現頻率較高的字符採用較短的編碼,對出現頻率較低的字符採用較長的編碼,它可以保證平均碼長最短,具有較高的編碼效率。因而哈夫曼編碼被廣泛應用於數據壓縮領域。
  • 面試官:給我手寫一個哈夫曼編碼(java語言實現)
    哈弗曼樹往往都會根據哈夫曼編碼結合著來說,因此這篇文章,主要結合著面試問題來說明。一、基本概念哈夫曼樹的目的是找出存放一串字符所需的最少的二進位編碼, 原理是通過統計出每種字符出現的頻率!不斷地對其合併。
  • 漫畫:什麼是 「哈夫曼樹」?
    作者 | 小灰來源 | 程式設計師小灰(ID:chengxuyuanxiaohui)————— 第二天 —————————————————概念1:什麼是路徑?概念2:什麼是路徑長度?在一棵樹中,從一個結點到另一個結點所經過的「邊」的數量,被我們稱為兩個結點之間的路徑長度。仍然用剛才的二叉樹舉例子,從根結點A到葉子結點H,共經過了3條邊,因此路徑長度是3。概念3:什麼是結點的帶權路徑長度?
  • golang哈夫曼編碼壓縮文件代碼實現全流程(超詳細版)
    :www.topgoer.com1.僅僅介紹了哈夫曼樹的機制,並沒有算法實現,只知道原理可不一定能寫出代碼2.代碼實現了哈夫曼樹的構造,並且完成編碼,存儲在string變量中,列印出被哈夫曼編碼過的字符串,這其實變相增大了文件的體積,是一種耍流氓,壓根沒有達到目的,沒有理解哈夫曼編碼的真正精髓是bit壓縮3.通過全局變量將編碼的table保存在內存中,而非保存在被壓縮的文件中
  • 床長人工智慧教程pdf下載——Java數據結構——哈夫曼
    哈夫曼樹又稱最優二叉樹,它是個帶權的葉子結點構成的所有二叉樹中帶權路徑長度最下的二叉樹。二哈夫曼樹的構造算法假設有個權值,則構造出的哈夫曼樹有個葉子結點。重複步,直到森林中剩一棵樹為止,該樹即為所求得的哈夫曼樹。
  • HEVC是個什麼「鬼」?
    之後這個粉絲兒問了小編一個十分可愛的問題——HEVC是個什麼」鬼「?鑑於電影發燒友不在少數,小編也想借這篇文章向廣大粉絲兒們科普一下HEVC硬解碼究竟是個什麼「鬼」,希望更多的粉絲兒有機會追求高品質的高清電影。HEVC,英文全拼是High Efficiency Video Coding,是一種新的視頻壓縮標準。視頻的硬解碼與軟解碼針對的就是HEVC的解碼。說到高清硬解碼,就不得不提到軟解。
  • 被高通看重的aptX究竟是個什麼鬼?
    Mesh大家都耳熟能詳了,那aptX是個什麼鬼?好,不賣關子,aptX是一個音頻編解碼標準,該標準和藍牙A2DP的立體聲音頻傳輸協議整合,就是一個技術的爆品,如何爆?我們先來看看我們現在面對的問題。採用藍牙耳機聽手機音樂,大家都知道,對不,這個很好用!但是你有沒有在家裡邊,戴著藍牙耳機看電視呢?有嗎?你真的有嗎?有很多產品嗎?
  • 吸血鬼×主僕 田中strike漫畫「吸血鬼僕人」動畫化決定!
    吸血鬼×主僕 田中strike漫畫「吸血鬼僕人」動畫化決定!   由日本漫畫家田中strike所作,連載於女性向少年漫畫雜誌《月刊ComicGENE》的「吸血鬼僕人」(SERVAMP-サーヴァンプ-)於今日宣布動畫化。
  • 海賊王漫畫976話什麼時候更新 海賊王漫畫976話鼠繪漢化在線看
    和之國篇對於鬼島的描述不少,想要打敗凱多就要拿到鬼島的設計圖紙,鬼島本身存在什麼神奇的地方呢?在遊戲海賊無雙4中,鬼島特寫領先與漫畫和動畫提前出現了,鬼島竟然是個火山? 官方正版的遊戲組自己腦補的可能性不大,對於鬼島是火山的設定,想必已經諮詢過原作了。
  • eBay小白科普:產品編碼MPN、UPC、EAN、ePID都是什麼鬼?
    為了能更合規化且系統化的運營,包括eBay在內的許多平臺已要求部分類別的賣家在其listing中添加產品編碼, 從而產生了MPN、UPC、EAN、GTIN、 ePID等縮略語的由來,這些編碼可以幫助eBay向買家展示相關產品並鼓勵谷歌等搜尋引擎在搜索結果中將產品listing放在更靠前的位置。但各個編碼含義以及來源的不同讓眾多賣家摸不著頭腦。
  • 《約定的夢幻島》「鬼」這個物種的分析
    (ヮ)點擊上方關注,獲取更多精彩內容ヽ( )ノ《約定的夢幻島》裡「鬼」是什麼?從目前動漫裡出現的「鬼」的模樣來看,越有權利的「鬼」身材越像人,說話、思維更與人類接近。有權力的鬼是啥呢?第一集中,「鬼」稱「柯尼」(編號:48294,因為學習成績不好被「出貨」,隨身帶著伊莎貝拉送給她的兔子玩偶,是個溫柔的女孩子。)
  • 夢見鬼是什麼預兆 白天做夢夢見鬼是什麼意思
    夢見鬼是什麼預兆 白天做夢夢見鬼是什麼意思孕婦夢見鬼意味著,與情人之間的感情微妙地感到有些不安,也因此讓你表現得比平常更黏人、追問不休。沒必要的忌妒心反而讓對方的心越離越遠了。即使內心不安表面上也要裝得平靜一點,慢慢拐個彎來套話吧。會發出閃光燈號的東西,這兩天的幸運物。
  • 輕鬆一刻:白吃村的「樹葉紙巾」什麼鬼,「上吊電梯」誰敢坐!
    輕鬆一刻:白吃村的「樹葉紙巾」什麼鬼,「上吊電梯」誰敢坐!旺財其實還是挺喜歡白吃村的,以為空氣非常的新鮮,風景也很好,唯一的就是白吃村廁所很難接受,特別就是白吃村的那個擦屁屁用的工具,太奇葩了!之後旺財跟呆頭一起出去突然看到了一個很高的石階,但是爬上去太辛苦了,呆頭看到後就帶著旺財去做電梯,可是旺財看到後直接就拒絕了!
  • 晚上夢見鬼是什麼預兆 晚上夢見鬼是什麼原因
    晚上夢見鬼是什麼預兆 晚上夢見鬼是什麼原因準備考試的人夢見鬼纏身,意味著可望錄取,但不能太大意或自信。談婚論嫁的人夢見鬼纏身,說明年紀懸殊,性情不合,婚姻難成。創業的人夢見鬼纏身,代表營利得財。防官司。