大家可否知道,檔案壓縮程式裡面的核心結構,核心演算法是什麼?或許你知道,他就運用了赫夫曼樹。
聽說赫夫曼勝過了他的導師,被認為」青出於藍而勝於藍「,這句話也是我比較欣賞的,嘻嘻。
一 概念
了解」赫夫曼樹「之前,幾個必須要知道的專業名詞可要熟練記住啊。
1: 結點的權
「權」就相當於「重要度」,我們形象的用乙個具體的數字來表示,然後通過數字的大小來決定誰重要,誰不重要。
2: 路徑
樹中從「乙個結點"到「另乙個結點「之間的分支。
3: 路徑長度
乙個路徑上的分支數量。
4: 樹的路徑長度
從樹的根節點到每個節點的路徑長度之和。
5: 節點的帶權路徑路勁長度
其實也就是該節點到根結點的路徑長度*該節點的權。
6: 樹的帶權路徑長度
樹中各個葉節點的路徑長度*該葉節點的權的和,常用wpl(weight path length)表示。
二: 構建赫夫曼樹
上面說了那麼多,肯定是為下面做鋪墊,這裡說赫夫曼樹,肯定是要說赫夫曼樹咋好咋好,赫夫曼樹是一種最優二叉樹,
因為他的wpl是最短的,何以見得?我們可以上圖說話。
現在我們做乙個wpl的對比:
圖a: wpl= 5*2 + 7*2 +2*2+13*2=54
圖b:wpl=5*3+2*3+7*2+13*1=48
我們對比一下,圖b的wpl最短的,地球人已不能阻止wpl還能比「圖b」的小,所以,「圖b"就是一顆赫夫曼樹,那麼大家肯定
要問,如何構建一顆赫夫曼樹,還是上圖說話。
第一步: 我們將所有的節點都作為獨根結點。
第二步: 我們將最小的c和a組建為乙個新的二叉樹,權值為左右結點之和。
第三步: 將上一步組建的新節點加入到剩下的節點中,排除上一步組建過的左右子樹,我們選中b組建新的二叉樹,然後取權值。
第四步: 同上。
三: 赫夫曼編碼
大家都知道,字元,漢字,數字在計算機中都是以0,1來表示的,相應的儲存都是有一套編碼方案來支撐的,比如asc碼。
這樣才能在"編碼「和」解碼「的過程中不會成為亂碼,但是asc碼不理想的地方就是等長的,其實我們都想用較少的空間來儲存
更多的東西,那麼我們就要採用」不等長」的編碼方案來儲存,那麼「何為不等長呢「?其實也就是出現次數比較多的字元我們採用短編碼,
出現次數較少的字元我們採用長編碼,恰好,「赫夫曼編碼「就是不等長的編碼。
這裡大家只要掌握赫夫曼樹的編碼規則:左子樹為0,右子樹為1,對應的編碼後的規則是:從根節點到子節點
a: 111
b: 10
c: 110
d: 0
四: 實現
不知道大家懂了沒有,不懂的話多看幾篇,下面說下赫夫曼的具體實現。
第一步:構建赫夫曼樹。
第二步:對赫夫曼樹進行編碼。
第三步:壓縮操作。
第四步:解壓操作。
1:首先看下赫夫曼樹的結構,這裡欄位的含義就不解釋了。
1#region 赫夫曼樹結構
2///
3///
赫夫曼樹結構
4///
5public
class huffmantree
6 89
public
int parent
1011
public
int left
1213
public
int right
14 }
15#endregion
2: 建立赫夫曼樹,原理在上面已經解釋過了,就是一步一步的向上搭建,這裡要注意的二個性質定理:
當葉子節點為n個,則需要n-1步就能搭建赫夫曼樹。
當葉子節點為n個,則赫夫曼樹的節點總數為:(2*n)-1個。
1#region 赫夫曼樹的建立
2///
3///
赫夫曼樹的建立
4///
5///
赫夫曼樹
6///
葉子節點
7///
節點權重
8public huffmantree createtree(huffmantree huffman, int leafnum, int weight)
9
20 }
2122
//這裡面也要注意,4個節點,其實只要3步就可以構造赫夫曼樹
23for (int i = leafnum; i < huffmannode; i++)
24
3839
return huffman;
40 }
41#endregion
4243
#region 選出葉子節點中最小的二個節點
44///
45///
選出葉子節點中最小的二個節點
46///
47///
48///
要查詢的結點數
49///
50///
51public
void selectnode(huffmantree huffman, int searchnodes, out
int minindex1, out
int minindex2)
52
7576
//如果為null,則認為當前實體為最小
77if (minnode2 == null)
78
98 }
99if (minnode1 != null && minnode2 != null)
100
111else
112
119 }
120 }
121 }
122 }
123 }
124#endregion
3:對哈夫曼樹進行編碼操作,形成一套「模板」,效果跟asc模板一樣,不過乙個是不等長,乙個是等長。
1#region 赫夫曼編碼
2///
3///
赫夫曼編碼
4///
5///
6///
7///
8public
string huffmancoding(huffmantree huffman, int leafnum)
9
3839 huffmancode[i] = new
string(codetemp.reverse().toarray());
40 }
41return huffmancode;
42 }
43#endregion
4:模板生成好了,我們就要對指定的測試資料進行壓縮處理
1#region 對指定字元進行壓縮
2///
3///
對指定字元進行壓縮
4///
5///
6///
7///
8public
string encode(string huffmancode, string alphabet, string test)
9
23 }
24 }
2526
return encodestr;
27 }
28#endregion
5: 最後也就是對壓縮的資料進行還原操作。
1#region 對指定的二進位制進行解壓
2///
3///
對指定的二進位制進行解壓
4///
5///
6///
7///
8///
9///
10public
string decode(huffmantree huffman, int huffmannodes, string alphabet, string test)
11
25if (test[i].tostring() == "1")
26
29 i++;
30 }
31 decodestr += alphabet[j];
32 }
33return decodestr;
34 }
3536
#endregion
最後上一下總的執行**
view code
基本演算法系列15天速成
演算法系列15天速成 第一天 七大經典排序 上 演算法系列15天速成 第二天 七大經典排序 中 演算法系列15天速成 第三天 七大經典排序 下 演算法系列15天速成 第四天 五大經典查詢 上 演算法系列15天速成 第五天 五大經典查詢 中 演算法系列15天速成 第六天 五大經典查詢 下 演算法系列1...
演算法系列15天速成 第十天 棧
今天跟大家聊聊棧,在程式設計中,棧的使用還是非常廣泛的,比如有 括號匹配問題 html結構匹配問題 所以說掌握了 棧 的使用,對我們學習演算法還是很有幫助的。一 概念 棧,同樣是一種特殊的線性表,是一種last in first out lifo 的形式,現實中有很多這樣的例子,比如 食堂中的一疊盤...
演算法系列15天速成 第十天 棧
今天跟大家聊聊棧,在程式設計中,棧的使用還是非常廣泛的,比如有 括號匹配問題 html結構匹配問題 所以說掌握了 棧 的使用,對我們學習演算法還是很有幫助的。一 概念 棧,同樣是一種特殊的線性表,是一種last in first out lifo 的形式,現實中有很多這樣的例子,比如 食堂中的一疊盤...