霍夫曼樹(最優二叉樹)的實現
文章目錄
一、相關概念
1.節點的路徑及路徑長度
路徑:在樹中,一個節點向下到達另一個節點的通路,稱為路徑。
路徑長度:路徑中經歷的分支數。
圖中節點1到節點4的路徑就是:1->2,2->4。路徑長度為2。
2.節點的帶權路徑長度
在樹中,可以定義某個節點的權值,從根節點到此節點的路徑長度與此節點的權值的乘積就是該節點的帶權路徑長度。
例如:上圖中若定義節點4的權值為4,則其帶權路徑長度為4*2=8。
3.樹的帶權路徑長度
樹中所有葉子節點的帶權路徑之和稱為樹的帶權路徑長度,簡稱WPL(weighted path length)。
4.霍夫曼樹
擁有相同葉子節點的所有樹中,WPL最小的樹稱為霍夫曼樹,又稱最優二叉樹。
上圖中右面的就為霍夫曼樹(未畫出所有情況)。
二、構建步驟與圖解
1.構建步驟
目標:給定一個數列arr,其中元素對應葉子節點的權值,以此構建霍夫曼樹。
- 將數列中各元素看成只有根節點的樹,按權值對各樹從小到大排序。
- 以其中最小的兩顆樹為左右子樹構建成一顆新的樹t,t的權值為兩子樹權值之和。
- 在數列中用t取代其左右子樹,再對剩下的樹按權值進行排序,並迴圈1,2步驟。
- 直到數列中只剩下一個元素,霍夫曼樹就構建成了。
2.圖解
以arr={2,3,4,12,7,6}為例。
1.排序{2,3,4,6,7,12},並取出前兩個。
2.變為{4,6,7,12,5},排序{4,5,6,7,12},取出前兩個。
3.變為{6,7,12,9},排序{6,7,9,12},取出前兩個。
4.變為{9,12,13},取出前兩個。
4.變為{13,21},取出前兩個。
5.4.變為{34},結束。
三、程式碼實現
1.建立節點類:
class Node implements Comparable<Node> {
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
//排序需求
@Override
public int compareTo(Node o) {
return this.value - o.value;//從小到大排序
}
//前序遍歷方法
public void preOrderTraversal(Node root){
if(root == null) return;
System.out.println(root);
preOrderTraversal(root.left);
preOrderTraversal(root.right);
}
}
2.建立霍夫曼樹
public static Node huffmanTree(int[] arr){
List<Node> nodes = new ArrayList<>();
for (int data : arr) {//用arr建立多個node節點,存到nodes中
nodes.add(new Node(data));
}
Node newNode = null;
//構建霍夫曼樹
while(nodes.size() > 1){
Collections.sort(nodes);
//System.out.println(nodes);
Node left = nodes.remove(0);
Node right = nodes.remove(0);
newNode = new Node(left.value + right.value);
newNode.left = left;
newNode.right = right;
nodes.add(newNode);
}
return newNode;
}
}
3.全部程式碼
public class HuffmanTree {
public static void main(String[] args) {
int[] arr = {2, 3, 4, 12, 7, 6};
Node root = huffmanTree(arr);
root.preOrderTraversal(root);
}
public static Node huffmanTree(int[] arr){
List<Node> nodes = new ArrayList<>();
for (int data : arr) {
nodes.add(new Node(data));
}
Node newNode = null;
while(nodes.size() > 1){
Collections.sort(nodes);
//System.out.println(nodes);
Node left = nodes.remove(0);
Node right = nodes.remove(0);
newNode = new Node(left.value + right.value);
newNode.left = left;
newNode.right = right;
nodes.add(newNode);
}
return newNode;
}
}
class Node implements Comparable<Node> {
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
@Override
public int compareTo(Node o) {
return this.value - o.value;//從小到大排序
}
//前序遍歷方法
public void preOrderTraversal(Node root){
if(root == null) return;
System.out.println(root);
preOrderTraversal(root.left);
preOrderTraversal(root.right);
}
}
相關文章
- 最優二叉樹(哈夫曼樹)Java實現二叉樹Java
- 滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜尋樹(二叉查詢樹)和最優二叉樹二叉樹
- 二叉樹實現二叉樹
- Java實現紅黑樹(平衡二叉樹)Java二叉樹
- js實現完全排序二叉樹、二叉搜尋樹JS排序二叉樹
- 資料結構之「霍夫曼樹」資料結構
- 二叉樹的遍歷實現二叉樹
- 平衡二叉樹(AVL樹)和 二叉排序樹轉化為平衡二叉樹 及C語言實現二叉樹排序C語言
- JavaScript 二叉搜尋樹以及實現翻轉二叉樹JavaScript二叉樹
- python 實現二叉樹的深度&&廣度優先遍歷Python二叉樹
- 二叉搜尋樹的python實現Python
- iOS實現反轉二叉樹iOS二叉樹
- java語言實現二叉樹Java二叉樹
- javascript實現二叉搜尋樹JavaScript
- python實現非平衡二叉樹Python二叉樹
- Python實現二叉樹的增、刪、查Python二叉樹
- 最優二叉查詢樹—動態規劃C++動態規劃C++
- 一本正經的聊資料結構(6):最優二叉樹 —— 哈夫曼樹資料結構二叉樹
- 資料結構中的樹(二叉樹、二叉搜尋樹、AVL樹)資料結構二叉樹
- 使用javascript實現排序二叉樹(2)JavaScript排序二叉樹
- 使用javascript實現排序二叉樹(1)JavaScript排序二叉樹
- 二叉查詢樹概念及實現
- 詳細二叉樹實現c++二叉樹C++
- java實現-資料結構之二叉樹(三):線索化二叉樹Java資料結構二叉樹
- 用Python實現二叉樹的增、刪、查Python二叉樹
- 二叉樹的插入和搜尋–python實現二叉樹Python
- 小結:二叉樹的幾種實現方式二叉樹
- 資料結構之樹結構概述(含滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜尋樹、紅黑樹、B-樹、B+樹、B*樹)資料結構二叉樹
- 二叉樹、B樹以及B+樹二叉樹
- 平衡二叉樹,B樹,B+樹二叉樹
- 二叉樹實現按層 s型列印二叉樹
- JavaScript實現簡單二叉查詢樹JavaScript
- 排序二叉樹和平衡二叉樹排序二叉樹
- 什麼是遍歷二叉樹,JavaScript實現二叉樹的遍歷(遞迴,非遞迴)二叉樹JavaScript遞迴
- 二叉樹(順序儲存二叉樹,線索化二叉樹)二叉樹
- 資料結構-二叉搜尋樹的實現資料結構
- 二叉樹的建立與遍歷(遞迴實現)二叉樹遞迴
- Java實現二叉搜尋樹的插入、刪除Java