zoukankan      html  css  js  c++  java
  • 最优二叉搜索树

    定义

           设  是有序集,且  ,表示有序集 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 是根
    ",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 的左孩子
    ",j,r);
            else  printf("d%d 是 k%d 的右孩子
    ",j,r);
            return;  
        }  
        else  
        {  
            if (rootChild < r)  printf("k%d 是 k%d 的左孩子
    ",rootChild,r); 
            else  printf("k%d 是 k%d 的右孩子
    ",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;
    } 
  • 相关阅读:
    494 Target Sum 目标和
    493 Reverse Pairs 翻转对
    492 Construct the Rectangle 构建矩形
    491 Increasing Subsequences 递增子序列
    488 Zuma Game 祖玛游戏
    486 Predict the Winner 预测赢家
    485 Max Consecutive Ones 最大连续1的个数
    483 Smallest Good Base
    Django Form组件
    Django Auth组件
  • 原文地址:https://www.cnblogs.com/VividBinGo/p/11960637.html
Copyright © 2011-2022 走看看