最優二分查詢樹
阿新 • • 發佈:2019-01-25
已知一批單詞及其頻率,我們希望找到這樣一個二叉樹,使找到所有的單詞的加權平均次數最低。
一個想法是,我們可以利用遞推,最優二叉樹的最低加權平均次數,等於最優左子二叉樹 + 最優右子二叉樹與自身消耗的和,和矩陣連乘最小運算次數的演算法是基本一樣的。
輸入:單詞數目,單詞及其對應頻率,如:
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(); } }