Ex 6_20 最优二叉搜索树..._第六次作业

 假设关键字的总数为n,用c[i,j]表示第i个关键字到第j个关键字的最优二叉查找树的代价,我们的目标是求c[0,n-1]。要求c[i,j],首先要从第i个关键字到第j个关键字中选一个出来作为根结点,选出根结点后,最优二叉搜索树的代价为左子树的代价加上右子树的代价,由于每选出一个根结点,每个关键字的搜索长度都增加1,因此得出递推式,即当

 1 package org.xiu68.ch06.ex6;
 2 
 3 public class Ex6_20 {
 4     //动态规划,最优二叉搜索树
 5     public static void main(String[] args) {
 6         // TODO Auto-generated method stub
 7         double[] w=new double[]{0.05,0.4,0.08,0.04,0.1,0.1,0.23};
 8         String[] words=new String[]{"begin","do","else","end","if","then","while"};
 9         int[][] roots=new int[w.length][w.length];        //i到j之间的二叉搜索树的根结点
10         optimalBST(w,roots);
11         
12         for(int i=0;i<roots.length;i++){
13             for(int j=0;j<roots[i].length;j++){
14                 System.out.print(roots[i][j]+"	");
15             }
16             System.out.println();
17         }
18         
19         printRoot(words, roots,0,w.length-1);
20         /*
21          最少平均比较次数为:2.18
22         0    1    1    1    1    1    1    
23         0    1    1    1    1    1    4    
24         0    0    2    2    4    4    6    
25         0    0    0    3    4    4    6    
26         0    0    0    0    4    4    6    
27         0    0    0    0    0    5    6    
28         0    0    0    0    0    0    6    
29         begin和while的根结点为 do
30         begin和begin的根结点为 begin
31         else和while的根结点为 while
32         else和then的根结点为 if
33         else和end的根结点为 else
34         end和end的根结点为 end
35         then和then的根结点为 then
36         */
37     }
38     
39     //roots中存放i到j之间的二叉搜索树的根结点
40     public static void optimalBST(double[] w,int[][] roots){
41         double[][] c=new double[w.length][w.length];    //i到j之间的二叉搜索树的最小代价
42         
43         
44         for(int i=0;i<w.length;i++){
45             c[i][i]=w[i];        //树只有自身,则代价为自身的频率
46             roots[i][i]=i;        //(i到j的树的根结点)自身作为根结点
47         }
48         
49         for(int s=2;s<=w.length;s++){            //s个单词作为子问题(子问题的规模)
50             for(int i=0;i<=w.length-s;i++){        //s个单词的第一个单词
51                 int j=i+s-1;                    //s个单词的最后一个单词
52                 
53                 double min=Double.MAX_VALUE;
54                 for(int k=i;k<=j;k++){            //寻找使平均查找次数最少的根结点
55                     double cLeft=0;                //以k作为根结点的左子树的代价
56                     double cRight=0;            //以k作为根结点的右子树的代价
57                     if(k>i)
58                         cLeft=c[i][k-1];
59                     if(k<j)
60                         cRight=c[k+1][j];
61                     if(cLeft+cRight<min){
62                         min=cLeft+cRight;
63                         roots[i][j]=k;
64                     }
65                 }//3
66                 double sum=0;
67                 for(int t=i;t<=j;t++){
68                     sum+=w[t];
69                 }
70                 c[i][j]=min+sum;
71             }//2
72         }//1
73         System.out.println("最少平均比较次数为:"+c[0][w.length-1]);
74     }
75     
76     //打印最优根
77     public static void printRoot(String[] words,int[][] roots,int i,int j){
78         if(i<=j){
79             int k=roots[i][j];
80             System.out.println(words[i]+"和"+words[j]+"的根结点为 "+words[k]);
81             printRoot(words,roots,i,k-1);
82             printRoot(words,roots,k+1,j);
83         }
84     }
85 }
View Code
原文地址:https://www.cnblogs.com/xiu68/p/7989067.html