構建哈夫曼樹及求它的帶權路徑長度

給定N個權值作爲N個葉子結點,構造一棵二叉樹,若該樹的帶權路徑長度達到最小,稱這樣的二叉樹爲最優二叉樹,也稱爲哈夫曼樹(Huffman Tree)。要構成哈夫曼樹,值比較大的葉子節點高度越低越好。

(1) 將n個權值看出n顆只有根節點的樹,構建n顆樹。
(2) 在森林中選出兩個根結點的權值最小的樹合併,作爲一棵新樹的左、右子樹,且新樹的根結點權值爲其左、右子樹根結點權值之和;
(3)從森林中刪除選取的兩棵樹,並將新樹加入森林;
(4)重複(2)(3)步n-1遍,最後森林中只有一棵樹,這棵樹就是哈夫曼樹。
(5)直接用遞歸求它的帶權路徑長度即可。

java參考代碼:


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class Main
{
	public static void main(String[] args) 
	{
		Scanner sc=new Scanner(System.in);
		int n = sc.nextInt();
		List<Tree> ts=new ArrayList<Tree>();
		//構建n顆只有根節點的樹
		for(int i=0;i<n;i++)
			ts.add(new Tree(sc.nextInt()));
		//進行n-1次,刪除最小的兩棵樹,合併兩棵樹並加進去
		for(int i=0;i<n-1;i++)
			removeAndAdd(ts);
		//求帶權路徑長度
		int ans=getNum(ts.get(0),0);
		System.out.println(ans);
		
	}
	
	private static int getNum(Tree tree,int n) 
	{
		if(tree.left==null&&tree.right==null)
			return tree.data*n;
		return getNum(tree.left, n+1)+getNum(tree.right, n+1);		
	}

	private static void removeAndAdd(List<Tree> ts) 
	{
		int min1=Integer.MAX_VALUE;
		int min2=Integer.MAX_VALUE;
		int inx1=-1;
		int inx2=-1;
		//找出兩個最小值
		for(int i=0;i<ts.size();i++)
		{
			Tree t=ts.get(i);
			if(t.data<min1)
			{
				min1=t.data;
				inx1=i;
			}
			else if(t.data<min2)
			{
				min2=t.data;
				inx2=i;
			}
		}
		
		//刪除兩顆最小的數,合併兩棵樹,並加入
		Tree t1=ts.get(inx1);
		Tree t2=ts.get(inx2);
		Tree t=new Tree(t1.data+t2.data);
		t.left=t1;
		t.right=t2;
		ts.remove(t1);
		ts.remove(t2);
		ts.add(t);
		
	}

	
}

class Tree
{
	int data;
	Tree left;
	Tree right;
	Tree(int data) {
		super();
		this.data = data;
	}

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