哈夫曼樹
最近學習了數據結構中哈夫曼樹的知識。
先來看哈夫曼樹的定義:給定n個權值作爲葉子節點,構造一棵二叉樹,如果該樹的帶權路徑長度(WPL)達到最小,則稱這樣的二叉樹爲最優二叉樹,也稱爲哈夫曼樹。
得明確幾個重要的概念:
- 路徑和路徑長度:在一棵樹中,從一個節點往下可以達到的孩子或孫子節點之間的通路,稱爲路徑。通路中分支的數目稱爲路徑長度。若規定根節點的層數爲1,則從根節點到第L層節點的路徑長度爲L-1。
- 節點的權及帶權路徑長度:若將樹中節點賦給一個有着某種含義的數值,則這個數值稱爲該節點的權,節點的帶權路徑長度爲:從根結點到該節點之間的路徑長度與該節點的權的乘積。
- 樹的帶權路徑長度:樹的帶權路徑長度規定爲所有葉子節點的帶權路徑長度之和,記爲WPL
如有錯誤之處,還望指出,定會及時改正。
package com.tree.huffmanTree;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/*
* 給定一個數組,創建哈夫曼樹
*/
public class HuffmanTreeDemo2 {
public static void main(String[] args) {
int[] arr = new int[10];
int num = 0;
int count = 0;
boolean flag = false;
while (count < arr.length) {
num = (int) (Math.random() * 20);
for (int i = 0; i < arr.length; i++) {
if (num == arr[i]) {
flag = true;
break;
}
}
if (!flag) {
arr[count++] = num;
} else {
flag = false;
}
}
System.out.println("原數組爲:" + Arrays.toString(arr));
// 創建成哈夫曼樹
Node2 huffmanTree = createHuffmanTree(arr);
// 前序遍歷哈夫曼樹
preList(huffmanTree);
}
public static Node2 createHuffmanTree(int[] arr) {
// 首先將數組中的每個數據轉換成Node,存放在list中
List<Node2> list = new ArrayList<Node2>();
for (int value : arr) {
list.add(new Node2(value));
}
// 開始創建哈夫曼樹
// 分析:1.首先要將list進行排序
// 2.排完序後,每次取出前兩個節點,也就是權值最小和次小節點;
// 3.將兩個節點組成一棵二叉樹,父節點權值即爲兩個節點權值之和
// 4.在list中將處理過的兩個節點刪除,將新的節點插入
// 5.重新排序
// 6.重複執行上述步驟,直到每個節點都處理完結束。也就是list中只剩一個節點,也就是哈夫曼樹的根節點
int count = 0;
while (list.size() > 1) {
// 1.將list進行排序
Collections.sort(list);
// 2.取出最小和次小節點
Node2 leftNode = list.get(0);
Node2 rightNode = list.get(1);
// 3.生成新節點,權值是兩個節點的權值之和
Node2 parent = new Node2(leftNode.value + rightNode.value);
// 4.綁定關係
parent.left = leftNode;
parent.right = rightNode;
// 5.刪除處理過的兩個節點
list.remove(leftNode);
list.remove(rightNode);
// 6.將新節點添加進list
list.add(parent);
System.out.println("第" + (++count) + "次處理後:" + list);
}
// 最後只剩一個節點,就是哈夫曼樹的根節點
return list.get(0);
}
// 前序遍歷
public static void preList(Node2 root) {
if (root != null) {
root.preList();
} else {
System.out.println("空樹無法遍歷!");
}
}
}
//定義節點類
//因爲要比較每個節點的大小,實現Comparable接口,實現compareTo方法
class Node2 implements Comparable<Node2> {
int value;// 權值
Node2 left;// 左子結點
Node2 right;// 右子節點
public Node2(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node2 [value=" + value + "]";
}
@Override
public int compareTo(Node2 o) {
// TODO Auto-generated method stub
return this.value - o.value;
}
// 前序遍歷
public void preList() {
System.out.println(this);
if (this.left != null) {
this.left.preList();
}
if (this.right != null) {
this.right.preList();
}
}
}