1. 程式人生 > >最優二分查詢樹

最優二分查詢樹

        已知一批單詞及其頻率,我們希望找到這樣一個二叉樹,使找到所有的單詞的加權平均次數最低。

        一個想法是,我們可以利用遞推,最優二叉樹的最低加權平均次數,等於最優左子二叉樹 + 最優右子二叉樹與自身消耗的和,和矩陣連乘最小運算次數的演算法是基本一樣的。

        輸入:單詞數目,單詞及其對應頻率,如:

         7
        break 0.22
        case 0.18
        char 0.20
        do 0.05
        return 0.25
        switch 0.02
        void 0.08

       打印出最低加權平均次數以及最優二叉查詢樹的前序遍歷,如:

       2.15

       char
       break
       case
       return
       do
       void
       switch

package OBST;
import java.util.Scanner;

public class OBST {
	public static class Cost{
		public double times;
		public int word;
		public Cost(){}
	}
	static int size;
	static double[] pro;
	static String[] str;
	static double[][] weight;
	static Cost[][] cost;
	static final double inf=10000;
	static double ans;

	public static void printOBSTree(int i,int j){
		if(j<i||j<0||i<0||j>=size||i>=size)return;
		System.out.println(str[cost[i][j].word]);
		printOBSTree(i,cost[i][j].word-1);
		printOBSTree(cost[i][j].word+1,j);
	}
	
	public static void findOBSTree(){
		Scanner in = new Scanner(System.in);
		size = in.nextInt();
		pro = new double[size];
		str = new String[size];
		weight = new double[size][size];
		cost = new Cost[size][size];
		
		for(int i=0;i<size;i++){
			for(int j=0;j<size;j++){
				cost[i][j] = new Cost();
			}
		}
		for(int i=0;i<size;i++){
			str[i] = in.next(); 
			pro[i] = in.nextDouble();

		}
		for(int i=0;i<size;i++){
			weight[i][i] = pro[i];
			for(int j=i+1;j<size;j++){
				weight[i][j]=weight[i][j-1]+pro[j];

			}
		}
		for(int i=0;i<size;i++){
			System.out.println(pro[i]);
			cost[i][i].times = pro[i];
			cost[i][i].word = i;
		}
		for(int k=2;k<=size;k++){
			for(int i=0;i<=size-k;i++){
				int j=i+k-1;
				cost[i][j].times=inf;
				for(int l=i;l<=j;l++){
					
					double tmp=weight[i][j]
							+((l>i)?cost[i][l-1].times:0)
							+((l<j)?cost[l+1][j].times:0);

					if(tmp<cost[i][j].times){
						cost[i][j].word = l;
						cost[i][j].times = tmp;
					}
				}
			}
		}
	    ans=cost[0][size-1].times;
	    System.out.println(ans);
	    printOBSTree(0,size-1);
		in.close();
	}
	
	public static void main(String args[]){
		findOBSTree();	
	}
}