數據結構——赫夫曼樹

赫夫曼樹

一:基本介紹

  1. 給定n個權值作爲n個葉子結點,構造一棵二叉樹,**若該樹的帶權路勁長度(wpl)達到最小,**稱這樣的二叉樹爲最優二叉樹,也稱爲赫夫曼樹(Huffman Tree),還有的書叫做霍夫曼樹,哈夫曼樹。
  2. 赫夫曼樹使帶權路徑長度最短的樹,權值較大的結點離根較近。

二:赫夫曼樹幾個重要的概念和舉例說明

  1. **路徑和路徑長度:**在一棵樹中,從一個結點往下可以達到的孩子結點或者孫子結點之間的通路,稱爲路徑!**通路中分支的數目稱爲路徑長度。若規定根結點的層數爲1,則從根節點到第L層結點的路徑長度爲L-1 **
  2. **結點的權及帶權路徑長度:**若將樹中結點賦值給一個有着某種含義的數值,則這個數值稱該節點的權。**結點的帶權路徑長度爲:**從根節點到該節點之間的路徑長度與該節點的權的乘積。
  3. 樹的帶權路徑長度:樹的帶權路徑長度規定爲**所有葉子節點的帶權路徑長度之和,**記爲WPL,權值越大的結點離根節點越近的二叉樹纔是最有二叉樹。
  4. 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;
    }

}

結果展示:

結果展示

發佈了26 篇原創文章 · 獲贊 5 · 訪問量 4155
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章