最優二叉樹(哈夫曼樹)Java實現
此篇部落格講最優二叉樹也叫哈夫曼樹的原理,以及構建步驟,還有哈夫曼編碼原理。建議有二叉樹基礎朋友學習交流。對二叉樹基礎可以看我的另外一篇部落格二叉樹的構建以及遍歷
哈夫曼樹引出:
我們平時期末成績判斷,不僅需要給出分數的具體值,還需要給出分數所處的段位,例如優秀、良好、及格、不及格;我們計算機怎樣進行判斷呢?
上面的判斷從最終結果來看並沒有什麼問題,但是我要要考慮效率,當我們每次拿到成績時候都要從是否及格開始一連串的判斷,這樣一定會使判斷效率低下。抽象成判斷樹如下:
一張優秀的試卷我們需要讓大量同學集中在中等或良好的範圍,優秀和不及格同學應該儘量的少。所以這棵樹我們還要考慮各層級學生佔比例問題,所以結點間聯絡要有權重。
如果按照上面程式碼那樣判斷,那麼百分之80的人都需要經過3次以上的判斷。這顯然不合理,所以我們可以考慮下面這樣組織判斷:
從上圖我們能看出大部分人不用經過多次判斷,但是我們是怎樣設計這樣的樹呢?這就是我們赫夫曼樹需要做的,赫夫曼樹也稱為最優二叉樹。
哈夫曼樹原理及實現
定義與原理
-
從樹中一個結點到另一個結點間的分支構成兩個結點間的路徑,路徑上的分支數目叫做路徑長度
例如上圖二叉樹a中從根結點到結點D路徑長度為4,二叉樹b為2。 -
樹的路徑長度就是根節點到樹中每一個結點路徑長度之和;
例如上圖二叉樹a的路徑長度之和為1+1+2+2+3+3+4+4=20。 -
考慮帶權的結點,樹的帶權路徑長度為(路勁X權重),只計算帶權的結點,不帶權相當於X0=0;
例如二叉樹a帶權路徑長度WPL為
我們赫夫曼樹就是求WPL最小的樹,既為赫夫曼樹。
哈夫曼樹構造
- 構造哈夫曼樹演算法步驟
- 以權值分別為W1、W2、W3…的n個結點,構成n棵二叉樹T1、T2、T3…Tn(意思就是剛開始預設每棵二叉樹只有一個結點,所以就是n個結點n棵二叉樹),組成森林F={T1、T2、T3…Tn}。
每顆二叉樹Ti僅有一個權值為Wi的根結點。 - 在F中選取兩顆根結點權值最小的樹,作為左右子樹構造一棵新二叉樹,並且置新二叉樹根節點權值為左右子樹根結點權值之和。(根節點權值=左右子樹根結點權值之和,葉子結點權值=Wi)
- 從F中刪除這兩棵二叉樹,並將新二叉樹加入到F中,讓它可以和別的剩餘二叉樹一起比較。
- 不斷重複2.3兩步,直到F中只有一棵二叉樹為止。
- F中最後剩下的二叉樹就是哈夫曼樹。
- 舉例演示
假如一篇文章中A出現頻率為27%,27就是結點A的權重,其它的A27,B8,C15,D15,E30,F5;他們加起來就是100%。
我們用上面構造哈夫曼樹方法來把他們構造成哈夫曼樹如下:
哈夫曼樹Java程式碼實現
哈夫曼樹的節點類,為了方便使用集合類的排序功能,實現了Comparable介面(可以不是實現該介面,此時需要實現排序功能)
package my.huffmanTree;
public class Node<T> implements Comparable<Node<T>> {
private T data;
private double weight;
private Node<T> left;
private Node<T> right;
public Node(T data, double weight){
this.data = data;
this.weight = weight;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public Node<T> getLeft() {
return left;
}
public void setLeft(Node<T> left) {
this.left = left;
}
public Node<T> getRight() {
return right;
}
public void setRight(Node<T> right) {
this.right = right;
}
@Override
public String toString(){
return "data:"+this.data+";weight:"+this.weight;
}
@Override
public int compareTo(Node<T> other) {
if(other.getWeight() > this.getWeight()){
return 1;
}
if(other.getWeight() < this.getWeight()){
return -1;
}
return 0;
}
}
然後:實現哈夫曼樹的主題類,其中包括兩個靜態的泛型方法,為建立哈夫曼樹和廣度優先遍歷哈夫曼樹
package my.huffmanTree;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
public class HuffmanTree<T> {
public static <T> Node<T> createTree(List<Node<T>> nodes){
while(nodes.size() > 1){
Collections.sort(nodes);
Node<T> left = nodes.get(nodes.size()-1);
Node<T> right = nodes.get(nodes.size()-2);
Node<T> parent = new Node<T>(null, left.getWeight()+right.getWeight());
parent.setLeft(left);
parent.setRight(right);
nodes.remove(left);
nodes.remove(right);
nodes.add(parent);
}
return nodes.get(0);
}
public static <T> List<Node<T>> breadth(Node<T> root){
List<Node<T>> list = new ArrayList<Node<T>>();
Queue<Node<T>> queue = new ArrayDeque<Node<T>>();
if(root != null){
queue.offer(root);
}
while(!queue.isEmpty()){
list.add(queue.peek());
Node<T> node = queue.poll();
if(node.getLeft() != null){
queue.offer(node.getLeft());
}
if(node.getRight() != null){
queue.offer(node.getRight());
}
}
return list;
}
}
最後:編寫一共測試端
package my.huffmanTree;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<Node<String>> list = new ArrayList<Node<String>>();
list.add(new Node<String>("a",7));
list.add(new Node<String>("b",5));
list.add(new Node<String>("c",4));
list.add(new Node<String>("d",2));
Node<String> root = HuffmanTree.createTree(list);
System.out.println(HuffmanTree.breadth(root));
// System.out.println(list);
}
}
相關文章
- 樹和二叉樹的基本運算實現-哈夫曼樹/哈夫曼編碼二叉樹
- 哈夫曼樹
- Java 樹結構實際應用 二(哈夫曼樹和哈夫曼編碼)Java
- 哈夫曼二叉樹原始碼 (轉)二叉樹原始碼
- 【筆記】哈夫曼樹筆記
- 一本正經的聊資料結構(6):最優二叉樹 —— 哈夫曼樹資料結構二叉樹
- 資料結構與演算法——赫夫曼樹(哈夫曼樹)資料結構演算法
- 資料結構-哈夫曼樹(python實現)資料結構Python
- 6.6 哈夫曼樹及其應用
- 哈夫曼樹學習筆記筆記
- php二叉樹與赫夫曼樹PHP二叉樹
- [java]java實現哈夫曼編碼Java
- 【資料結構X.11】程式碼實現 哈夫曼樹的建立,建立,構造,實現哈夫曼編碼資料結構
- 高階資料結構---赫(哈)夫曼樹及java程式碼實現資料結構Java
- 重學資料結構之哈夫曼樹資料結構
- 哈夫曼樹及其應用(檔案壓縮)
- 霍夫曼樹(最優二叉樹)的實現二叉樹
- 資料結構與演算法:哈夫曼樹資料結構演算法
- POJ 3253-Fence Repair(哈夫曼樹-最小值優先佇列)AI佇列
- 樹(4)--赫夫曼樹及其應用
- 【資料結構】哈夫曼樹的建立與基礎應用資料結構
- 哈夫曼編碼 —— Lisp 與 Python 實現LispPython
- 二叉樹java實現二叉樹Java
- Java實現紅黑樹(平衡二叉樹)Java二叉樹
- 資料結構之哈弗曼樹資料結構
- 滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜尋樹(二叉查詢樹)和最優二叉樹二叉樹
- 合併果子(優先佇列 +或者+哈夫曼)佇列
- POJ 3253Fence Repair(哈夫曼&優先佇列)AI佇列
- C#資料結構-赫夫曼樹C#資料結構
- java語言實現二叉樹Java二叉樹
- 哈夫曼實現檔案壓縮解壓縮(c語言)C語言
- 二叉樹實現二叉樹
- java實現-資料結構之二叉樹(三):線索化二叉樹Java資料結構二叉樹
- js實現完全排序二叉樹、二叉搜尋樹JS排序二叉樹
- 平衡二叉樹(AVL樹)和 二叉排序樹轉化為平衡二叉樹 及C語言實現二叉樹排序C語言
- Java 樹結構實際應用 四(平衡二叉樹/AVL樹)Java二叉樹
- java實現樹Java
- Java二叉樹Java二叉樹