哈夫曼編碼是資料結構中比較基礎的東西。最近遇到乙個類似哈夫曼編碼的問題,解法卻截然不同。
問題a君:n堆石子排成一列,兩兩合併成一堆,只能相鄰的合併。合併的代價為兩堆石子個數之和。總的代價為所有中間結果之和。
求最小總代價。
也就是有次序的哈夫曼樹。
對比兩個問題後,開始思考哈夫曼編碼的正確性問題。
回顧一下哈夫曼編碼:
哈夫曼編碼的構造代價為
cost=所有葉子節點代價*葉子節點的層數.
哈夫曼編碼用的是一種貪心的方法來構造最小代價樹,如下:
1.n個節點,取最小代價的兩個節點合併為乙個,新的節點代價為兩個子節點代價之和
2.通過1步驟,變為n-1個節點.重複1過程,直到只剩乙個節點.
問題a君如果用哈夫曼的貪心演算法,優先合併最小和,得出的並不是最優解.
我開始思考,這種代價與哈夫曼建樹的代價有什麼區別.
為什麼哈夫曼樹的cost能用貪心,而這種樹的cost不能.
首先從哈夫曼編碼的正確性入手,思考為什麼貪心是最優的。
哈夫曼編碼的正確性證明:
1. 代價小的節點,層次一定最大.
用反證法.
如果a,b兩個節點不是代價最小的,如,a>c>b.
那麼交換a,c的位置,明顯代價會減小c-a>0;
也就是交換後代價會變小.即當前不是最優解.
上面表明,如果得到的樹是最優的,那麼一定節點越小,層次越大.
通過這一步的證明,再看問題a。由於構造順序是固定的,故不滿足這一條定律.由此也可以解釋,為什麼貪心的方法不適用於他.
2. 下面證明,越早構造合併的節點,層次越大.
假設a,b,c,d,e五個節點,代價為a<b<c按照貪心的規則,首先會合併a,b兩個節點,得到a+b.
我們用c(a)表示a的層次.
因為在a,b構造之後,所有的節點權值之和只可能大於a+b.
也就是c+d+e>e+d>c+e>c+d>a+b.
按照貪心規則,a+b或跟單個節點c,e,合併;或跟c+d合併,得到如下樹形.
此時c(a),c(b)>=c(c).
而下圖這種樹形是不可能構造出來的.
也就證明了c(a),c(b)>=c(c).
上面用屌絲的推理方式。之所以這樣稱呼,因為證明並不是基於嚴格的數學推導。
在證明的過程中,也順便得出了,問題a,順序最小代價樹的非貪心特性.小結一下:
1.由於順序是固定的,所以越小的不一定層次越大,因為其轉化為更優解也許不滿足次序.
2.還是由於次序固定,先合併的層次不一定最大.
那麼問題a用什麼方法呢?想到了動態規劃。
下面用動態規劃解決上面的問題:
由於最後生成樹一定是兩個子樹合併,有n-1種情況,即:
用f(1,n)表示1到n節點的最優解,則得到我們的動態規劃遞推公式:
f(1,n)=max(f(1,1)+f(2,n),f(1,2)+f(3,n),………f(1,n-1)+f(n,n)).
f(i,i)=a[i];
最後編碼解決上述問題:
int max(int left,int right)
return maxx;
}int f()}}
哈夫曼樹構造演算法的正確性證明
哈夫曼樹構造 1 哈夫曼樹的定義 給定n個權值作為n個葉子結點,構造一棵二叉樹,若帶權路徑長度達到最小,稱這樣的二叉樹為最優二叉樹,也稱為哈夫曼樹 huffman tree 2 哈夫曼樹的構造 假設有n個權值,則構造出的哈夫曼樹有n個葉子結點。n個權值分別設為 w1,w2,wn,則哈夫曼樹的構造規則...
哈夫曼樹構造演算法的正確性證明
哈夫曼樹構造 1 哈夫曼樹的定義 給定n個權值作為n個葉子結點,構造一棵二叉樹,若帶權路徑長度達到最小,稱這樣的二叉樹為最優二叉樹,也稱為哈夫曼樹 huffman tree 2 哈夫曼樹的構造 假設有n個權值,則構造出的哈夫曼樹有n個葉子結點。n個權值分別設為 w1,w2,wn,則哈夫曼樹的構造規則...
資料結構之哈夫曼樹及哈夫曼編碼
當樹中的節點被賦予乙個表示某種意義的數值,我們稱之為該節點的權。從樹的根節點到任意節點的路徑長度 經過的邊數 與該節點上權值的乘積稱為該節點的帶權路徑長度。樹中所有葉節點的帶權路徑長度之和稱為該樹的帶權路徑長度 wpl 當帶權路徑長度最小的二叉樹被稱為哈夫曼樹,也成為最優二叉樹。如下圖所示,有三課二...