1. 程式人生 > 實用技巧 >赫夫曼樹

赫夫曼樹

赫夫曼樹介紹:

  • 1)給定n個權值作為n個吐子結點,構造一棵二叉樹,若該樹的帶權路徑長度(wpl)達到最小,稱這樣的二叉樹為最優二二叉樹,也稱為哈夫曼樹(Huffmanree),還有的書翻譯為霍夫曼樹。
  • 2)赫夫曼樹是帶權路徑長度最短的樹,權值較大的結點離根較近。

赫夫曼樹概念:

  1. 路徑和路徑長度:在一棵樹中,從一個結點往下可以達到的孩子或孫子結點之間的通路,稱為路徑。通路中分支的數目稱為路徑長度。若規定根結點的層數為1,則從根結點到第L層結點的路徑長度為L-1,結點的權及帶權路徑長度:若將樹中結點賦給一個有 著某種含義的數值,
  2. 則這個數值稱為該結點的權。結點的帶權路徑長度為:從根結點到該結點之間的路徑長度與該結點的權的乘積

權:        比如給節點賦值為13,這個節點的權就是13
帶權路徑:   從root節點到13號節點的路徑為:3-1 = 2
帶權路徑長度:13 * 2 = 26
wpl:       所有帶權路徑的長度之和:13*2 + 7*2 + 8*2 + 3*2 = 62
WPL最小的就是赫夫曼樹(保證所給的節點都是葉子節點)

如何構建赫夫曼樹:

赫夫曼樹的程式碼實現:

import java.util.ArrayList;
import java.util.Collections;

public class Test04_赫夫曼樹 {
    public static
void main(String[] args) { int[] arr = {13, 7, 8, 3, 29, 6, 1}; Node root = heFuMan(arr);//返回的是二叉樹的頭 qianXuOrder(root); } //前序遍歷的方法 public static void qianXuOrder(Node root) { if (root != null) { root.qianXuOrder(); } else { System.out.println(
"二叉樹為空,無法進行遍歷!"); } } /** * 建立赫夫曼樹的方法 * * @param arr : 傳入要進行轉換為赫夫曼樹的陣列 * @return : 返回建立為赫夫曼樹的root節點 */ public static Node heFuMan(int[] arr) { int count = 0; //1、為了操作方便,就將arr陣列的每一個元素構建成一個Node ArrayList<Node> list = new ArrayList<>(); for (int value : arr) { list.add(new Node(value));//每一個元素就成為了一個Node } //如果集合中只剩下最後一個元素的時候就跳出迴圈 while (list.size() > 1) { //將集合進行排序 Collections.sort(list); System.out.println("第"+(++count)+"次進行排序後的二叉樹為:" + list); //2、取出兩個最小的葉子節點,構建二叉樹 Node leftNode = list.get(0); Node rightNode = list.get(1); //構建二叉樹 Node newTree = new Node(leftNode.value + rightNode.value); newTree.left = leftNode; newTree.right = rightNode; //從ArrayList集合中刪除已經使用過的節點 list.remove(leftNode); list.remove(rightNode); //將新的二叉樹新增到ArrayList集合中去 list.add(newTree); System.out.println("新構建的二叉樹:" + list); } //返回赫夫曼樹的頭 return list.get(0); } } /** * 建立節點類Node * 實現Comparable介面是為了對集合進行排序操作 */ class Node implements Comparable<Node> { int value;//節點的權值 Node left;//指向左子節點 Node right;//指向右子節點 public Node(int value) { this.value = value; } //對節點進行前序遍歷的方法 public void qianXuOrder() { System.out.println(this); if (this.left != null)//左子節點不為空就繼續向左遍歷 this.left.qianXuOrder(); if (this.right != null) this.right.qianXuOrder(); } public String toString() { return "Node{" + "value=" + value + '}'; } public int compareTo(Node node) { //表示從小到大進行排序 return this.value - node.value; } }