zoukankan      html  css  js  c++  java
  • 最优二叉查找树_动态规划

    原问题是给出各个节点和各个节点的被查找概率,然后构造一棵各个节点平均被查找比较次数最小的树,则该问题可以用动态规划来解决

    示例如下

    推广到一般的情况,并设T(i, j)是由记录{ri, …, rj}(1≤i≤j≤n)构成的二叉查找树,C(i, j)是这棵二叉查找树的平均比较次数,有下列分析

    观察这个表,可知可知左边的表的第一行的第四列就是我们要求的最优平均比较次数,而右边的表我们可以知道在c(i ,j)得到最优解,即平均查找次数最小的根节点,比如一共四个节点,则我们从右边的R(1,4)的值即3是这四个节点构成的树的根节点。则树的左子树变为c(1,2),他的根节点是r(1,2)=2,然后2又有左节点1,而4则是3的根节点。则树的样子便出来了。

    代码如下

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 double BST(int n,double p[],double c[][100],int r[][100])
     4 {
     5     for(int i=1;i<=n;i++){//按式1和式2初始化
     6         c[i][i-1]=0;
     7         c[i][i]=p[i];
     8         r[i][i]=i;
     9     }
    10     c[n+1][n]=0;
    11     for(int d=1;d<n;d++){//安对角线计算,此时是n-1个对角线
    12         for(int i=1;i<=n-d;i++){//行的取值范围
    13             int j=i+d;//求出在对角线上的i对应的j
    14             double minnum=99999.0;//出是一个较大的值
    15             int mink=i;
    16             double sum=0;
    17             for(int k=i;k<=j;k++)
    18             {
    19                 sum=sum+p[k];
    20                 if(c[i][k-1]+c[k+1][j]<minnum){//不断比较,获取最小的值
    21                     minnum=c[i][k-1]+c[k+1][j];
    22                     mink=k;
    23                 }
    24             }
    25             c[i][j]=minnum+sum;//得到了最小值
    26             r[i][j]=mink;//记录取得最小值时的根节点
    27         }
    28 
    29     }
    30     return c[1][n];
    31 }
    32 int main()
    33 {
    34     cout << "请输入树的节点的个数" << endl;
    35     int n;
    36     cin >> n;
    37     cout << "请输入每个节点的被查找概率" << endl;
    38     double p[n];
    39     memset(p,0,sizeof(p));
    40     for(int i=1;i<=n;i++)
    41     {
    42         cin >> p[i];
    43     }
    44     double c[n+2][100];
    45     int r[n+2][100];
    46     memset(r,0,sizeof(r));
    47     memset(c,0,sizeof(c));
    48      double s=BST(n,p,c,r);
    49      cout << "最小平均比较次数为" << s<<endl;
    50      cout << "平均最小概率矩阵如下:" << endl;
    51      for(int i=1;i<=n+1;i++){
    52         for(int j=0;j<=n;j++){
    53             cout << c[i][j] << "   ";
    54         }
    55         cout << endl;
    56      }
    57 
    58      cout << "最优二叉查找树对应的根节点 " << endl;
    59 for(int i=1;i<=n+1;i++){
    60         for(int j=0;j<=n;j++){
    61             cout << r[i][j] << "   ";
    62         }
    63         cout << endl;
    64      }
    65 
    66     return 0;
    67 }

    运行结果如下

    具体树的构造我们可以从数组r求出,等我有空再把代码补上,用程序把树的构造描绘出来

  • 相关阅读:
    matlab矩阵中如何去掉重复的行;如何找到相同的行,并找到其位置
    Coursera 机器学习 第9章(下) Recommender Systems 学习笔记
    机器学习基石笔记1——在何时可以使用机器学习(1)
    Coursera 机器学习 第9章(上) Anomaly Detection 学习笔记
    matlab安装过程的被要求的配置程序
    jdk环境变量配置
    Coursera 机器学习 第8章(下) Dimensionality Reduction 学习笔记
    Coursera 机器学习 第8章(上) Unsupervised Learning 学习笔记
    Coursera 机器学习 第7章 Support Vector Machines 学习笔记
    linux服务器---squid限制
  • 原文地址:https://www.cnblogs.com/henuliulei/p/10074216.html
Copyright © 2011-2022 走看看