以字串「aaaabbbccd」為例實現檔案壓縮。
(1)統計各字元出現個數
a:4
b:3
c:2
d:1
(2)利用各字元出現的次數作為權值構建huffman樹
哈夫曼樹又稱為最優二叉樹,是加權路徑長度最短的二叉樹。
構建規則:每次在給定資料中挑選出兩個權值最小的數,分別作為左右孩子節點,構建乙個父節點將兩個孩子節點鏈結起來,父節點權值等於左右孩子權值之和,然後再將父節點放回存放資料的序列;重複過程,直到所有資料存放數中。下圖以1,2,3,4四個數字為例構建哈夫曼樹。右邊為得到的huffman編碼。
(3)進行壓縮
壓縮之前檔案中存放的是「aaaabbbccd「一共10個位元組;進行編碼後每個字元可以使用一段二進位制序列表示對應的編碼,同樣上圖的編碼,寫入檔案資訊就是」0000(4個a)101010(3個b)111111(2個c)110(1個d),佔19個位元位,所以占用3個位元組,原檔案中10個字元都是char型,所以占用10個位元組,以此達到huffman樹檔案壓縮的效果。
huffman壓縮演算法壓縮率高的情況就是出現特別多的重複字元(如上圖中的」a」),只有少數是別的字元。效率低的情況就是每個字元出現的次數基本相同。
注意點:(4)解壓縮 拿著壓縮檔案進行讀取並重新寫入檔案。1)向檔案中寫入資訊時,按照二進位制讀寫方式寫入;每次向記憶體寫入乙個位元組;最後若不滿乙個位元組,單獨進行判斷補0.
2)建立配置檔案:在解壓縮時,如果沒有配置檔案,那麼檔案中只有0101序列,根本不知道寫的是什麼;所以需要增加配置檔案,在壓縮檔案的開頭先記錄出現的每個字元以及對應出現的次數,方便解壓縮時重建huffman樹。
注意點:(1)當待壓縮檔案中出現來了中文,程式就會崩潰,最後發現是陣列越界的錯誤,程式中使用char型別為陣列下標(0~127),如果只是字元它的範圍是-128~127,而漢字的編碼是兩個位元組,因此需要將char型別強轉為unsigned char,可表示範圍為0~2551)先讀取配置檔案重新構建huffman; 2)壓縮過程中最後的填充位導致資料冗餘。
3)解壓縮的過程就是拿著我們之前壓縮檔案中的資訊進行重新構建huffman樹,按照對應的編碼翻譯出對應的字元即可。
4)由壓縮檔案還原檔案的時候如何知道壓了多少字元呢?當壓縮的時候最後一位補了0的在解壓縮的時候可能會把這個補的位當成原字元的編碼來處理。如何解決呢?一種想法是在統計字元出現的次數的時候設定乙個變數,每讀取乙個字元該變數的值就+1,最後將該變數寫進配置檔案中;另外一種想法就是根據根節點的權值,由上例不難看出根節點權值中的_count就是字元出現的次數。
(2)特殊情況處理:當遇到\n,程式函式就是讀取一行字元,但若字元本身末尾就含有』\n『,需要特殊處理。讀取配置檔案時如果讀到了』\n』,說明字元本身就是』\n』,應繼續讀取它的次數。
**存放:[
檔案壓縮專案測試步驟分析
測試用例情況分析:
總體思路:
(1)統計:讀取乙個字元,統計出256個字元中各個字元出現的總次數。
(2)建樹:按照字元出現的次數,並以次數作為權值建立哈夫曼樹,然後產生各個字元的哈夫曼編碼。
(3)壓縮:再次讀取檔案,按照該字元對應的編碼寫到新的編碼檔案中。
(4)加工:將檔案的長度,檔案中各個字元以及他們出現的次數,寫進編碼檔案中。
(5)解壓:利用壓縮檔案和配置檔案恢復出原檔案。
(6)測試:帶入測試用例,觀察解壓出的檔案和原檔案是否相同。
哈夫曼樹和哈夫曼編碼(檔案壓縮)
哈夫曼樹 huffman tree 帶權路徑長度 wpl 設二叉樹有n個葉子結點,每個葉子結點帶有權值wk,從根節點到每個葉子結點的長度為lk,則每個葉子結點帶權路徑長度之和就是 wk lk 求和 最優二叉樹或哈夫曼樹 wpl最小的二叉樹 哈夫曼樹的構造 每次把權值最小的兩棵二叉樹合併 1 huff...
檔案壓縮(哈夫曼樹實現)
專案描述 專案簡介 利用哈夫曼編碼的方式對檔案進行壓縮,並且對壓縮檔案可以解壓 開發環境 windows vs2013 專案概述 1.壓縮 a.讀取檔案,將每個字元,該字元出現的次數和權值構成哈夫曼樹 b.哈夫曼樹是利用小堆構成,字元出現次數少的節點指標存在堆頂,出現次數多的在堆底 c.每次取堆頂的...
檔案壓縮(哈夫曼壓縮)
檔案壓縮總結 哈夫曼壓縮 在學習哈弗曼壓縮之前,還是首先來了解什麼是哈夫曼樹,哈夫曼編碼。1.哈夫曼樹是一種最優二叉樹,它的帶權路徑長度達到最小。樹的帶權路徑長度為所有葉子結點帶權路徑長度之和。而結點的帶權路徑長度是結點的路徑長度乘以結點的權值。2.哈夫曼編碼是依據字元出現概率來構造異字頭的平均長度...