首页 > 其他 > 详细

最优二叉搜索树

时间:2019-11-30 14:28:28      阅读:68      评论:0      收藏:0      [点我收藏+]

定义

       设 技术分享图片 是有序集,且 技术分享图片 ,表示有序集 S 的二叉搜索树利用二叉树的结点来存储有序集中的元素。它具有下述性质:存储于每个结点中的元素 x 大于其左子树中任一结点所存储的元素,小于其右子树中任一结点所存储的元素。二叉搜索树的叶节点是形如 技术分享图片的开区间。在表示 S 的二叉搜索树中搜索一个元素 x ,返回的结果有两种情况:

       ①  在二叉搜索树的内结点中找到 技术分享图片,令其概率为 技术分享图片

       ②  在二叉搜索树的叶节点中确定 技术分享图片 ,令其概率为 技术分享图片 。技术分享图片表示 x 小于 技术分享图片 的值的概率,技术分享图片 表示所有 x 大于 技术分享图片 的值的概率,技术分享图片表示 x 位于 技术分享图片 和 技术分享图片 值的概率。

       显然,有 技术分享图片技术分享图片技术分享图片技术分享图片 称为集合 S 的存取概率分布。

       在表示 S 的二叉搜索树 T 中,设存储元素 技术分享图片 的结点深度为 技术分享图片,叶节点  技术分享图片 的结点深度为 技术分享图片,则

 

技术分享图片

 

      表示在二叉搜索树 T 中进行一次搜索所需的平均比较次数,p又称为二叉搜索树 T 的平均路长。在一般情况下,不同的二叉搜索树的平均路上是不相同的。

      所以,最优二叉搜索树问题是对于有序集 S 及其存取概率分布 技术分享图片 ,在所有表示有序集 S 的二叉搜索树中找出一颗具有最小平均路长的二叉搜索树。

最优子结构性质

       二叉搜索树 T 的一棵含有结点 技术分享图片 和叶节点 技术分享图片 的子树可以看做是有序集 技术分享图片 关于全集合技术分享图片 的一棵二叉搜索树,其存取概率为下面的条件概率

 

                                                                        技术分享图片

技术分享图片

技术分享图片

 

          设 技术分享图片 是有序集 技术分享图片 关于存取概率 技术分享图片 的一棵最优二叉搜索树,其平均路长为 技术分享图片技术分享图片 的根结点存储元素 技术分享图片。其左右子树 技术分享图片 和 技术分享图片 的平均路长分别为 技术分享图片 和 技术分享图片。由于技术分享图片 和 技术分享图片 中结点深度是他们在 技术分享图片 中的结点深度减1,所以得出

 

技术分享图片

 

       由于 技术分享图片 是关于集合 技术分享图片 的一棵二叉搜索树,故 技术分享图片。若技术分享图片,则用 技术分享图片 替换 技术分享图片 可得到平均路长比 技术分享图片 更小的二叉搜索树。这与技术分享图片 是最优二叉搜索树矛盾。故 技术分享图片 是一棵最优二叉搜索树。同理,技术分享图片也是一棵最优二叉搜索树。

       因此最优二叉搜索树问题具有最优子结构性质。

实现

 

技术分享图片

 

#include <iostream>  
using namespace std;  
const int MaxVal=9999,n=5;  
double p[n+1] = {-1,0.15,0.1,0.05,0.1,0.2};  //搜索到内部节点的概率  
double q[n+1] = {0.05,0.1,0.05,0.05,0.05,0.1};  //搜索到虚拟键的概率  
int root[n+1][n+1];  //记录根节点  
double w[n+2][n+2];  //子树概率总和  
double e[n+2][n+2];  //子树期望代价  
void optimalBST(int n)  
{  
    int i,j,k,len;
    for (i=1;i<=n+1;++i)  
    {  
        w[i][i-1]=q[i-1];  
        e[i][i-1]=q[i-1];  
    }  
    for(len=1;len<=n;++len)  
    {  
        for(i=1;i<=n-len+1;++i)  
        {  
            j=i+len-1;  
            e[i][j]=MaxVal;  
            w[i][j]=w[i][j-1]+p[j]+q[j];  
            for(k=i;k<=j;++k)  
            {  
                double temp=e[i][k-1]+e[k+1][j]+w[i][j];  
                if (temp<e[i][j])  
                {  
                    e[i][j]=temp;  
                    root[i][j]=k;  
                }  
            }  
        }  
    }  
}  
void printOptimalBST(int i,int j,int r)  
{  
    int rootChild = root[i][j];
    if (rootChild == root[1][n])  
    {  
        printf("k%d 是根\n",rootChild);
        printOptimalBST(i,rootChild - 1,rootChild);  
        printOptimalBST(rootChild + 1,j,rootChild);  
        return;  
    }  
    if (j < i - 1)  return;  
    else if (j == i - 1)  
    {  
        if (j < r)  printf("d%d 是 k%d 的左孩子\n",j,r);
        else  printf("d%d 是 k%d 的右孩子\n",j,r);
        return;  
    }  
    else  
    {  
        if (rootChild < r)  printf("k%d 是 k%d 的左孩子\n",rootChild,r); 
        else  printf("k%d 是 k%d 的左孩子\n",rootChild,r); 
    }  
    printOptimalBST(i,rootChild - 1,rootChild);  
    printOptimalBST(rootChild + 1,j,rootChild);  
}  
  
int main()  
{  
    optimalBST(n);  
    cout << "最优二叉树结构:" << endl;  
    printOptimalBST(1,n,-1);  
    system("pause");
    return 0;
} 

最优二叉搜索树

原文:https://www.cnblogs.com/VividBinGo/p/11960637.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!