Java 實現Haffman樹

Haffman Tree 的Java實現

I 哈夫曼樹概念:

        給定n個權值作爲n個葉子結點,構造一棵二叉樹,若帶權路徑長度達到最小,稱這樣的二叉樹爲最優二叉樹,也稱爲哈夫曼樹(Huffman Tree)。哈夫曼樹是帶權路徑長度最短的樹,權值較大的結點離根較近。(from Baidu百科)。

II 哈夫曼樹的應用

    1、哈夫曼編碼

    2、常應用於信息檢索

    etc.

III 常用術語

    

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

3、樹的帶權路徑長度
樹的帶權路徑長度規定爲所有葉子結點的帶權路徑長度之和,記爲WPL。
哈夫曼樹






IV 下面重點介紹一下haffman Tree的Java實現,代碼附下:

package pers.me.timlong.tree;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;

public class HaffmanTree {

	/**
	 * 內部靜態類Node
	 * @author lenovo
	 *
	 * @param <E>
	 */
	public static class Node<E>{
		private E data;
		private double weight;
		private Node<E> leftChild;
		private Node<E> rightChild;

		public Node(E data, double weight) {
			this.data = data;
			this.weight = weight;
		}

		@Override
		public String toString() {
			return "Node[data = " + this.data + ", weight = " + this.weight + "]";
		}
	}

	private static <E> void swap(List<Node<E>> nodes, int i, int j) {
		Node<E> temp;
		temp = nodes.get(i);
		nodes.set(i, nodes.get(j));

		nodes.set(j, temp);
	}
	
	//實現快速排序,對節點進行排序
	private static <E> void subSort(List<Node<E>> nodes, int start, int end) {
		if(start < end) {
			Node<E> base = nodes.get(start);
			int i = start;
			int j = end + 1;
			while(true) {
				while(i < end && nodes.get(++ i).weight >= base.weight) ;
				while(j > start && nodes.get(-- j).weight <= base.weight) ;
				
				if(i < j)
					swap(nodes, i, j);
				else 
					break;
			}
			
			swap(nodes, start, j);
			subSort(nodes, start, j);
			subSort(nodes, start, j - 1);
		}
	}
	
	public static <E> void quickSort(List<Node<E>> nodes) {
		subSort(nodes, 0, nodes.size() - 1);
	}
	
	@SuppressWarnings("rawtypes")
	public static List<Node> breadthFirst(Node root){
		Queue<Node> queue = new ArrayDeque<>();
		List<Node> list = new ArrayList<Node>();
		if(null != root) {
			queue.offer(root);
		}
		while(! queue.isEmpty()) {
			list.add(queue.peek());  //not remove
			Node p = queue.poll();  //remove
			if(null != p.leftChild) {
				queue.offer(p.leftChild);
			}
			if(null != p.rightChild) {
				queue.offer(p.rightChild);
			}
		}
		return list;
	}
	
	public static<E> Node<E> createTree(List<Node<E>> nodes){
		while(nodes.size() > 1) {
			quickSort(nodes);
			Node<E> left = nodes.get(nodes.size()  - 1);
			Node<E> right = nodes.get(nodes.size() - 2);
			
			Node<E> parent = new Node<E>(null, left.weight + right.weight);
			parent.leftChild = left;
			parent.rightChild = right;
			
			nodes.remove(nodes.size() - 1);
			nodes.remove(nodes.size() - 1);
			
			nodes.add(parent);
			
		}
		
		return nodes.get(0);
	}
		
	public static void main(String[] args) {
		List<Node<String>> nodes = new ArrayList<Node<String>>();
		nodes.add(new Node<String>("A", 40.0));
		nodes.add(new Node<String>("B", 7.0));
		nodes.add(new Node<String>("C", 10.0));
		nodes.add(new Node<String>("D", 30.0));
		nodes.add(new Node<String>("E", 12.0));
		nodes.add(new Node<String>("F", 2.0));
		Node<String> root = HaffmanTree.createTree(nodes);
		System.out.println(HaffmanTree.breadthFirst(root));
	}
}

打印結果:

[Node[data = null, weight = 101.0], 
Node[data = null, weight = 44.0],
Node[data = null, weight = 57.0], 
Node[data = null, weight = 14.0], 
Node[data = D, weight = 30.0], 
Node[data = null, weight = 17.0], 
Node[data = A, weight = 40.0], 
Node[data = F, weight = 2.0], 
Node[data = E, weight = 12.0], 
Node[data = B, weight = 7.0], 
Node[data = C, weight = 10.0]]

    在編程中的應用無處不在,掌握數據結構的底層實現,無疑可以更好地幫助我們提高編程能力與開發效率。

      望每天進步一點,再見

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