最优二叉查找树

  • 一、问题描述
  • 二、动态规划算法解题思路
  • 三、解题思路图形化
  • 四、思考:为什么输入概率相同(无序),输出结果不一样
    • 流程图
    • 实例
    • 示例代码

一、问题描述

1、问题描述:
基于统计先验知识,我们可统计出一个数表(集合)中各元素的查找概率,理解为集合各元素的出现频率。比如中文输入法字库中各词条(单字、词组等)的先验概率,针对用户习惯可以自动调整词频——所谓动态调频、高频先现原则,以减少用户翻查次数。这就是最优二叉查找树问题:查找过程中键值比较次数最少,或者说希望用最少的键值比较次数找到每个关键码(键值)。为解决这样的问题,显然需要对集合的每个元素赋予一个特殊属性——查找概率。这样我们就需要构造一颗最优二叉查找树。
  n个键{a1,a2,a3…an},其相应的查找概率为{p1,p2,p3…pn}。构成最优BST,表示为T1n ,求这棵树的平均查找次数C[1, n](耗费最低)。换言之,如何构造这棵最优BST,使得C[1, n] 最小。

二、动态规划算法解题思路

动态规划法策略是将问题分成多个阶段,逐段推进计算,后继实例解由其直接前趋实例解计算得到。对于最优BST问题,利用减一技术和最优性原则,如果前n-1个节点构成最优BST,加入一个节点 an 后要求构成规模n的最优BST。按 n-1, n-2 , … , 2, 1 递归,问题可解。自底向上计算:C[1, 2]→C[1, 3] →… →C[1, n]。为不失一般性用C[i, j] 表示由{a1,a2,a3…an}构成的BST的耗费。其中1≤i ≤j ≤n。这棵树表示为Tij。从中选择一个键ak作根节点,它的左子树为Tik-1,右子树为Tk+1j。要求选择的k 使得整棵树的平均查找次数C[i, j]最小。左右子树递归执行此过程。(根的生成过程)
引用书上求解递归式:

以输入节点概率 :0.10 0.15 0.20 0.25 0.30为例
在计算C[ i ] [ j ]是需要从上往下按对角线计算,:

下面我们来计算C [ 1 ] [ 2 ] :
1<=i<=j<=2;
I<=k<=j;

三、解题思路图形化

下面介绍一种更为直观的三角形计算方法,其实本质没有发生改变,只是把数学公式图形化,方便填表。
求C[i][j]时,设以C[i][i-1],C[j+1][j],C[i][j]三个点形成的直角三角形的次斜边上的值累加和为S(斜),直角边上对应两点的和为S(直),显然S[直]有j-i+1个,则C[i][j]=S[斜]+min{S[直]}。更方便的理解为将最优树划分为左右子树,寻求其最小和值(构建最优二叉树),同时也能由k值确认最优的根节点值。
下面举个例子求C[1][3]的值,如图所示:

S(斜)=0.1+0.2+0.4=0.7,S(直)=min{S1(直),S2(直),S3(直)}=min{0+0.8,0.1+0.4,0.4+0}=0.4,则C[1][3]=0.7+0.4=1.1。同理,求C[[2]][[4]],如下图所示,C[[2]][[4]]=1.4:

四、思考:为什么输入概率相同(无序),输出结果不一样

总结一句话就是:输入数据是有序的,12345分别代表其根值大小,即第一个输入概率对应的值是1,第二个是2,查找的时候并不是根据概率查找,而是根据根值来构造最优二叉查找树。下面详细分析:

  1. 输出树不一致
    遇到的问题是输入同样的数据,就是各个概率顺序不一样,为什么得到的最优二叉查找树不一样。
    例如:每个节点对应的查找概率值:0.10 0.15 0.20 0.25 0.30

那么最优二叉树画出来就是:

但是当输入概率是:0.25 0.10 0.15 0.20 0.30

那么最优二叉树画出来就是:

  1. 从这两个图可以看出来,它们的最优平均查找次数不一样,连树画出来也不一样。 刚开始我是考虑怎样最优二叉树的查找,如果按照我刚开始的理解就是按照概率查找,其实是错的。那么按照概率查找,第二种二叉树的画法就出错了,因为从根节点0.15 看,它的左右子节点都比它大,下一步就不知道该查找那边的节点了。

  2. 那么我想了一种解决方法,就是像图一的二叉树一样,将二叉树的概率进行升序排序,那么它的查找树就会符合最优二叉树的查找方法,它的左边节点全部小于根节点,右边的左根节点都大于根节点。如果一定要排序的话那么就说明并不具有通用性,这个动态规划的查找最优二叉树的算法就出错了。

  3. 那么我就开始考虑是否是我错了,算法算出的每一种结果都是对的,然后我就将所有概率换成了根节点。经过多次的结果验证,发现每个图都符合最优二叉树查找的规律,经过仔细的思考我终于理解了:因为查找的键值是根据根节点,而不是根据概率,而且每个键值都是升序。就像跟几点是1,2 ,3 ,4 ,5,那么它的键值大小排序就是1<2<3<4<5,这也就解释了求概率矩阵的时候为什么c[ I ] [ j ]是i到j时连续的,而不是跳变的。所以这个问题隐藏了一个条件,就是输入的概率对应的键值是升序,那么第二个最优二叉树应该是:

流程图

详细流程图

实例

输入输入概率:0.25 0.10 0.15 0.20 0.30

对应最优二叉查找树:

示例代码

C++写的代码:

//最优二叉查找树
#include<bits/stdc++.h>using namespace std;//const int maxval = 9999;double BST(int n,double p[],double c[][100],int r[][100])
{for(int i=1;i<=n;i++){c[i][i-1]=0;   //Ci矩阵初始化c[i][i]=p[i];r[i][i]=i;      //R根矩阵初始化}c[n+1][n]=0;for(int d=1;d<n;d++)        //安对角线计算,从第二条对角线开始{for(int i=1;i<=n-d;i++)     //行的取值范围{int j=i+d;          //j求出在对角线上的i对应的double minval=9999;int mink=i;         //最小值对应根点double sum=0;for(int k=i;k<=j;k++){sum=sum+p[k];if(c[i][k-1]+c[k+1][j]<minval)   //三角形比较法,选最小值{minval=c[i][k-1]+c[k+1][j];mink=k;}}c[i][j]=minval+sum;//得到了最小值r[i][j]=mink;//记录取得最小值时的根节点}}return c[1][n];
}int main()
{while(1){cout<<"input operand :  1  enter   ,2   exit system"<<endl;int ch;cin>>ch;if(ch==2)return 0;else if(ch==1){system("cls");int n;cout << "input the point number" << endl;cin>>n;  //节点个数double p[n];  // 概率数组memset(p,0,sizeof(p));// 将概率数组排序,保证正确cout<<"input each point probability" <<endl;for(int i=1;i<=n;i++){cin>>p[i];}double c[n+2][100];  //动态ci矩阵int r[n+2][100];    //根矩阵memset(r,0,sizeof(r));memset(c,0,sizeof(c));double s=BST(n,p,c,r);cout << "the minimum compare times is  " << s<<endl;cout << "the minimum probability  matrix is" << endl;for(int i=1;i<=n+1;i++){for(int j=0;j<=n;j++){cout<<std::setw(3);cout << c[i][j] << "    ";}cout << endl;}cout << "the point matrix " << endl;for(int i=1;i<=n+1;i++){for(int j=0;j<=n;j++){cout << r[i][j] << "   ";}cout << endl;}}}
}

最优二叉查找树—动态规划C++相关推荐

  1. 算法导论之动态规划(最长公共子序列和最优二叉查找树)

    动态规划师通过组合子问题的解而解决整个问题,将问题划分成子问题,递归地求解各子问题,然后合并子问题的解而得到原问题的解.和分治算法思想一致,不同的是分治算法适合独立的子问题,而对于非独立的子问题,即各 ...

  2. 【算法学习】最优二叉查找树(动态规划)

    一.什么是最优二叉查找树 最优二叉查找树: 给定n个互异的关键字组成的序列K=<k1,k2,...,kn>,且关键字有序(k1<k2<...<kn),我们想从这些关键字中 ...

  3. 最优二叉查找树(动态规划)——详解

    最优二叉查找树 (1)二叉查找树(二分检索树)二叉搜索树 T是一棵二元树,它或者为空,或者其每个结点含有一个可以比较大小的数据元素,且有: T的左子树的所有元素比根结点中的元素小: T的右子树的所有元 ...

  4. DP之最优二叉查找树

    前面说过动态规划最典型的就是解决最优化问题的(具有最优子结构的最优化问题),最优二叉查找树就是一个典型的最优化问题. 问题描述: 给定一个n元素的中序序列,它可以有卡特兰数个不同形状的二叉排序树.(卡 ...

  5. 动态规划-最优二叉查找树

    1.先来看一下最优二叉树: 2.举个例子: 平局比较次数: 计算比较的平均次数: 3.其中最主要的推导公式: 其中:C[i][j]表示二叉查找树T(i,j)的平均比较次数:R[i][j]表示二叉查找树 ...

  6. 最优二叉查找树 次优二叉查找树 最优二叉树

    未完成.. 在数据结构课本中,查找,作为倒数的章节介绍,不是因为它不重要,而是它本身作为一种数据结构比较简单.但实用用性较强. 按照查找的引出的先后顺序介绍: 1. 静态查找(树)表 以下介绍的是有序 ...

  7. noi 2009 二叉查找树 动态规划

    思路: 先把权值离散化 按数据值排序 sum[i]为前i个节点频度和 dp[i][j][w]表示把节点[i,j]合并成一颗根节点权值不小于w的子树所需的访问代价与修改代价的最小和 dp[i][j][w ...

  8. 第十五章 动态规划——最优二叉搜索树

    1.前言: 接着学习动态规划方法,最优二叉查找树问题.二叉查找树参考http://www.cnblogs.com/Anker/archive/2013/01/28/2880581.html.如果在二叉 ...

  9. 动态规划最优二叉搜索树C语言,【算法导论】动态规划之“最优二叉搜索树”...

    详解动态规划之"最优二叉搜索树" 之前两篇分别讲了动态规划的"钢管切割"和"矩阵链乘法",感觉到了这一篇,也可以算是收官之作了.其实根据前两 ...

最新文章

  1. PHP关键字'var'有什么作用?
  2. UA MATH567 高维统计II 随机向量4 Frame、凸性与各向同性
  3. OpenCV学习——轮廓检测
  4. 开始入坑深度学习(DeepLearning)
  5. C++结构体中const使用场景
  6. “变形金刚”为何强大:从模型到代码全面解析Google Tensor2Tensor系统
  7. oracle怎么以时间排序,查询表怎样按修改时间排序
  8. ApacheCN 计算机视觉译文集 20210203 更新
  9. nginx+tomcat+redis实现session共享
  10. 戴尔电脑开机之后闪黄灯系统不能启动
  11. Tomcat控制台乱码
  12. pku 3592 Instantaneous Transference tarjan缩点重建图+spfa求最长路
  13. python3.6对MySQL数据恢复
  14. 用于微信管理的社群工具
  15. 金彩教育:店铺装修色彩怎么搭配
  16. 实时系统vxWorks - 配置多网口
  17. 键盘输入一个高精度的正整数n,去掉任意s个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的n和s,寻找一种方案,使得剩下的数最小
  18. 深入理解Java虚拟机之走进Java之Java的发展历程
  19. HDU题目分类大全【大集合】
  20. model.predict_classes(test) 和model.predict(test) 区别

热门文章

  1. QT5 创建“打开文件”按钮
  2. GlusterFS基础知识
  3. Mac 所有zsh命令都失效怎么办
  4. 南京航空航天大学计算机学院研究生,南京航空航天大学计算机学院2016研究生推免办法...
  5. 无线蓝牙耳机性价比排行,2022年值得入手的蓝牙耳机
  6. PPP HOWTO 中译版
  7. java uml类图举例,uml类图(uml类图实例作业)
  8. 51Nod 1453(CF553-A) - 抽彩球(Kyoya and Colored Balls) - 解题报告
  9. 拼多多启动第四届农货节:携手10万涉农店铺,与8.8亿消费者共享“秋收喜悦”
  10. 怎么剪gif图的尺寸?