JAVA代碼創建哈夫曼樹

哈夫曼樹

最近學習了數據結構中哈夫曼樹的知識。
先來看哈夫曼樹的定義:給定n個權值作爲葉子節點,構造一棵二叉樹,如果該樹的帶權路徑長度(WPL)達到最小,則稱這樣的二叉樹爲最優二叉樹,也稱爲哈夫曼樹。
得明確幾個重要的概念:

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

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章