赫夫曼樹
一:基本介紹
- 給定n個權值作爲n個葉子結點,構造一棵二叉樹,**若該樹的帶權路勁長度(wpl)達到最小,**稱這樣的二叉樹爲最優二叉樹,也稱爲赫夫曼樹(Huffman Tree),還有的書叫做霍夫曼樹,哈夫曼樹。
- 赫夫曼樹使帶權路徑長度最短的樹,權值較大的結點離根較近。
二:赫夫曼樹幾個重要的概念和舉例說明
- **路徑和路徑長度:**在一棵樹中,從一個結點往下可以達到的孩子結點或者孫子結點之間的通路,稱爲路徑!**通路中分支的數目稱爲路徑長度。若規定根結點的層數爲1,則從根節點到第L層結點的路徑長度爲L-1 **
- **結點的權及帶權路徑長度:**若將樹中結點賦值給一個有着某種含義的數值,則這個數值稱該節點的權。**結點的帶權路徑長度爲:**從根節點到該節點之間的路徑長度與該節點的權的乘積。
- 樹的帶權路徑長度:樹的帶權路徑長度規定爲**所有葉子節點的帶權路徑長度之和,**記爲WPL,權值越大的結點離根節點越近的二叉樹纔是最有二叉樹。
- WPL最小的就是赫夫曼樹
如上圖:第二顆樹的wpl最小,因此第二棵樹就是赫夫曼樹!!
三:創建赫夫曼樹的思路
給定一個數組{13,7,8,3,29,6,1},要求轉成一顆赫夫曼樹
步驟:
1):將數組中的每一個元素轉換成一個結點,並存入到集合中
2):對集合進行從小到大排序,這裏Node結點繼承Comparable接口,重寫compareTo方法
3):取出集合中根節點權值最小的兩顆結點(二叉樹)
4):組成一棵新的二叉樹,該新的二叉樹都根節點的權值是前面兩顆二叉樹根節點權值的和
5):再將這顆新的二叉樹,以根節點的權值大小,再次進行排序,不斷重複以上步驟,直到數列中的所有數據都被處理,就得到一棵赫夫曼樹。
數組得到的赫夫曼樹如下:
四:代碼實現
package Huffman;
import java.util.*;
public class HuffmanTree {
public static void main(String[] args) {
//創建數組
int[] arr = {13,7,8,3,29,6,1};
Node root = creatHuffmanTree(arr);
preOrder(root);
}
//前序遍歷方法
public static void preOrder(Node root){
if (root!=null){
root.preOrder();
}else {
System.out.println("當前樹爲空樹");
}
}
//創建哈夫曼樹方法
public static Node creatHuffmanTree(int[] arr){
//將數組中元素創建成結點並存放在集合中
List<Node> list = new ArrayList<>();
for (int val : arr) {
list.add(new Node(val));
}
while (list.size()>1){
//先對集合進行排序
Collections.sort(list);
//然後取出最小的兩個值
Node leftNode = list.get(0);
Node rightNode = list.get(1);
//在創建一個父節點
Node parent = new Node(leftNode.value + rightNode.value);
parent.left = leftNode;
parent.right = rightNode;
//刪除集合中的最小的兩個值
list.remove(leftNode);
list.remove(rightNode);
//將父節點添加到集合中
list.add(parent);
}
return list.get(0);
}
}
//樹結點
class Node implements Comparable<Node>{
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
//前序遍歷
public void preOrder(){
System.out.println(this);
//左
if (this.left!=null){
this.left.preOrder();
}
if (this.right!=null){
this.right.preOrder();
}
}
//重寫toString方法
@Override
public String toString() {
return
"value=" + value +
' ';
}
//重寫比較方法
@Override
public int compareTo(Node o) {
return this.value - o.value;
}
}