/**
最优二叉查找树:一棵有n个结点的二叉查找树,已知每个结点的查找概率Pi(且∑Pi=1),要使查找操作的平均比较次数最小。(这里讨论的是成功查找,不讨论不成功的查找)
动态规划:
c[i][j]表示由结点i~j组成的BST成功查找的最小平均查找次数。
r[i][j]表示由结点i~j构成最优二叉查找树时的树根结点。
转换公式:
c[i][j] = Min[i<=k<=j]{c[i,k-1] + c[k+1,j]} + Sum{Pi...Pj};
时间复杂度是O(n^3)
优化:把原来的树根可能是i->j中的任何一个,优化成r[i,j-1] <= r[i,j] <= r[i+1,j]
可以证明优化后的时间复杂度是O(n^2)
**/
const int MAXN = 1000 + 5;
double c[MAXN][MAXN];
int r[MAXN][MAXN];
double optimalBST(int n, double p[])
{
double sum[MAXN] = {0};
for (int i = 1; i <= n; i++) // 求前i项和是为了简化后面的计算
sum[i] = sum[i-1] + p[i];
if ( fabs(sum[n] - 1.0) > 1e-6 ) // 检验∑Pi=1
return -1.0;
for (int i = 1; i <= n; i++) // initialize
{
c[i][i-1] = 0;
c[i][i] = p[i];
r[i][i] = i;
}
c[n+1][n] = 0;
for (int d = 1; d < n; d++)
{
for (int i = 1; i <= n-d; i++)
{
int j = i + d;
int root = -1;
double minv = 1e9;
for (int k = r[i][j-1]; k <= r[i+1][j]; k++) // k = i -> j 的优化
{
if (minv > c[i][k-1] + c[k+1][j])
{
minv = c[i][k-1] + c[k+1][j];
root = k;
}
}
r[i][j] = root;
c[i][j] = minv + sum[j] - sum[i-1];
}
}
return c[1][n];
}
最优二叉查找树(optimal BST)
原文作者:二叉查找树
原文地址: https://blog.csdn.net/morgan_xww/article/details/7014286
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/morgan_xww/article/details/7014286
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。