最优二叉搜索树

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <list>
 4 #include <vector>
 5 
 6 using namespace std;
 7 
 8 double e[10][10];//e[i][j]表示在k[i-1]和k[j+1]之间的关键字(全开区间)作为一颗有根树的最小搜索代价
 9 double w[10][10];//w[i][j]表示在k[i-1]和k[j+1]之间的关键字(全开区间)的概率之和
10 double optimal_bst(double *p, double *q, const int n) {//n为关键字数量,假装n小于9,(逃
11     for (int i = 1;i <= n + 1;i++)
12         w[i][i - 1] = q[i - 1], e[i][i - 1] = q[i - 1];
13     //e[1][n]
14     //状态转移方程:e[i][j]=e[i][r-1]+p[r]+e[r+1][j]+w[i][r-1]+w[r+1][j],其中两个w为区间内点下降获得的代价
15     //方程可转化为:e[i][j]=e[i][r-1]+e[r+1][j]+w[i][j]
16     for(int l=1;l<=n;l++)
17         for (int beg = 1;beg <= n - l + 1;beg++) {
18             int end = beg + l - 1;
19             w[beg][end] = w[beg][end - 1] + p[end] + q[end];
20             e[beg][end] = INT_MAX;
21             for (int root = beg;root <= end;root++)
22                 e[beg][end] = min(e[beg][end], e[beg][root - 1] + e[root + 1][end] + w[beg][end]);
23         }
24     cout << e[1][n] << endl;
25     return e[1][n];
26 }

感觉这个比较妙的主要是状态的定义,e[i][j]表示在k[i-1]和k[j+1]之间的关键字(全开区间)作为一颗有根树的最小搜索代价,w[i][j]表示在k[i-1]和k[j+1]之间的关键字(全开区间)的概率之和,同时也把e[i][i-1]和w[i][i-1]的情况包括进去了,即伪节点的概率,除了注意一些边界问题,难度还行。以上,跑过书里的一个例子,答案2.75

 

1 int main(void) {
2     double p[10] = { 0.0,0.15,0.10,0.05,0.10,0.20 };
3     double q[10] = { 0.05,0.10,0.05,0.05,0.05,0.10 };
4     optimal_bst(p, q, 5);
5 
6     return 0;
7 }

 

posted on 2018-04-01 13:13  只是个回忆录  阅读(152)  评论(0编辑  收藏  举报

导航