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

         OBST问题:用二叉树来存数据,不同数据访问频率不一样,怎么样构建这颗二叉树,才可以使得访问代价最小。

         直观的想法是把访问频率最高的放到树的根节点,树越矮越好,但是,很容易举出例子证明这种想法是错的,正确的做法是用动态规划。

         先讲讲用到的变量:

        p[ n ]是n个节点的频率数组,

        e[ i ][ j ] 表示第 i 个节点到第 j 个节点构成的子树的最小搜索代价值,

        w[ i ][ j ]表示第 i 个节点到第 j 个节点的频率和。

         一个事实:如果r是e[ i ][ j ]的根节点(i<=r<=j)那么:

        e[ i ][ j ]=e[ i ][ r-1 ] + e[ r+1 ][ j ] +w[ i ][ j ]  ( i<=j )

      同时定义边界:e[ i ][ j ]=0   ( j=i-1 )

      动态转移方程:

        e[ i ][ j ]=min{ e[ i ][ r-1 ] + e[ r+1 ][ j ] +w[ i ][ j ] }

      用到了3层循环,第一层循环变量是子树的节点个数,第二层循环的变量是子树的起点位置,第三层循环的变量是子树的根节点位置,如此,我们可以得到任意区间OBST的搜索期望是多少。

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #define INF 9999;
     5 
     6 void Optimal_BST(double p[],int n){
     7     int i,j,l,r;
     8     int root[n+1][n+1];
     9     double e[n+2][n+2];
    10     double w[n+2][n+2];
    11     for(i=1;i<=n+1;i++){
    12         e[i][i-1]=0;
    13         w[i][i-1]=0;
    14     }
    15     
    16     for(l=1;l<=n;l++){
    17         for(i=1;   i<=n-l+1;  i++){  // i,j between 1 and n+1,i是左边界,j是右边界 
    18             j=i+l-1;
    19             e[i][j]=INF;
    20             w[i][j]=w[i][j-1]+p[j];     
    21             for(r=i;r<=j;r++){
    22                 double temp=e[i][r-1]+e[r+1][j]+w[i][j];
    23                 if(temp<e[i][j]){
    24                     e[i][j]=temp;
    25                     root[i][j]=r;
    26                 }
    27             }
    28         }
    29     }
    30     printf("
    
    e table
    ");    
    31     for(i=1;i<=n;i++){
    32         for(j=1;j<=n;j++){
    33             if(i>j)printf("          ");
    34             else printf("%f  ",e[i][j]);
    35         }
    36         printf("
    ");
    37     }
    38     
    39     printf("
    
    w table
    ");
    40     for(i=1;i<=n;i++){
    41         for(j=1;j<=n;j++){
    42             if(i>j)printf("          ");
    43             else printf("%f  ",w[i][j]);
    44         }
    45         printf("
    ");
    46     }
    47 
    48     printf("
    
    root table
    ");
    49     for(i=1;i<=n;i++){
    50         for(j=1;j<=n;j++){
    51             if(i>j)printf("  ");
    52             else printf("%d ",root[i][j]);
    53         }
    54         printf("
    ");
    55     }
    56 }
    57 
    58 int main(){
    59     int n=5;
    60     double p[6]={-1,0.25,0.2,0.05,0.2,0.3};
    61     Optimal_BST(p,n);
    62     return 0;
    63 }
  • 相关阅读:
    51nod1089(最长回文子串之manacher算法)
    51nod1088(最长回文子串)
    51nod1256(乘法逆元)
    51nod1085(01背包)
    51nod1079(中国剩余定理)
    数据的特征工程
    30种提高mysql处理速度的方法
    机器学习资料
    python3.6安装-windows
    python import sklearn出错 "ImportError: DLL load failed: 找不到指定的模块。
  • 原文地址:https://www.cnblogs.com/houshengtao/p/6105849.html
Copyright © 2011-2022 走看看