概述
由相同權值的一組葉子結點所構成的二叉樹可能有不同的形態和不同的帶權路徑長度,具有最小帶權
路徑長度的二叉樹稱爲赫夫曼(Haffman)樹。也稱最優二叉樹,它是n個帶權葉子節點構成的所有二
叉樹中,帶權路徑長度最小的二叉樹。
節點的權:二叉樹中的每個葉子節點經常對應一個有實際意義的數據,這個數據稱爲該節點的權。
帶權路徑長度(WPL):樹中所有葉子節點的帶權路徑長度之和。在二叉樹中,二叉樹的路徑長
度是指由根節點到所有葉子節點的路徑長度之和。假設二叉樹具有n個帶權值的葉節點,那麼從根節點
到各個葉子節點的路徑長度與相應節點權值的乘積之和叫做二叉樹的帶權路徑長度(weighted path
length)。
如上圖所示:
(a)
WPL = 92+42+52+22 = 40
(b)
WPL = 91+52+43+23 = 37
(c)
WPL = 41+22+53+93 = 50
綜上可知:二叉樹的帶權路徑長度 WPL = 節點的權值乘以從根節點到當前節點所經過的節點數,也
可以看出,權值越大的節點離根節點越近的二叉樹纔是最優二叉樹。
創建赫夫曼樹流程分析
1、排序
2、取出根節點權值最小的兩棵二叉樹
3、組成新的一棵二叉樹,前面取出來的兩棵樹是新二叉樹的兩棵子樹
4、根節點的權值是前面取出來的兩棵二叉樹的根節點的權值之和
代碼展示
節點類
package demo8;
public class Node implements Comparable<Node>{
int value;
int left;
int right;
public Node(int value){
this.value = value;
}
@Override
public int compareTo(Node o) {
return -(this.value-o.value);
}
@Override
public String toString() {
return "Node{" + "value=" + value + '}';
}
}
測試類
package demo8;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestHuffmanTree {
public static void main(String[] args) {
int[] arr = new int[]{3,7,8,29,5,11,23,14};
Node node = createHuffmanTree(arr);
System.out.println(node);
}
//創建赫夫曼樹
public static Node createHuffmanTree(int[] arr){
//先使用數組中所有的元素創建若干個二叉樹(開始只有一個節點)
List<Node> nodes = new ArrayList<>();
for(int value:arr){
nodes.add(new Node(value));
}
//循環處理
while(nodes.size()>1){
//排序
Collections.sort(nodes);
//取出權值最小的兩個二叉樹
//取出權值最小的二叉樹
Node left = nodes.get(nodes.size()-1);
//取出權值次小的二叉樹
Node right = nodes.get(nodes.size()-2);
//創建一棵新的二叉樹
Node parent = new Node(left.value+right.value);
//把取出來的兩棵二叉樹移除
nodes.remove(left);
nodes.remove(right);
//放入原來的二叉樹集合中
nodes.add(parent);
}
return nodes.get(0);
}
}