一、问题描述
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,查找的时候并不是根据概率查找,而是根据根值来构造最优二叉查找树。下面详细分析:
- 输出树不一致
遇到的问题是输入同样的数据,就是各个概率顺序不一样,为什么得到的最优二叉查找树不一样。
例如:每个节点对应的查找概率值:0.10 0.15 0.20 0.25 0.30
那么最优二叉树画出来就是:
但是当输入概率是:0.25 0.10 0.15 0.20 0.30
那么最优二叉树画出来就是:
-
从这两个图可以看出来,它们的最优平均查找次数不一样,连树画出来也不一样。 刚开始我是考虑怎样最优二叉树的查找,如果按照我刚开始的理解就是按照概率查找,其实是错的。那么按照概率查找,第二种二叉树的画法就出错了,因为从根节点0.15 看,它的左右子节点都比它大,下一步就不知道该查找那边的节点了。
-
那么我想了一种解决方法,就是像图一的二叉树一样,将二叉树的概率进行升序排序,那么它的查找树就会符合最优二叉树的查找方法,它的左边节点全部小于根节点,右边的左根节点都大于根节点。如果一定要排序的话那么就说明并不具有通用性,这个动态规划的查找最优二叉树的算法就出错了。
-
那么我就开始考虑是否是我错了,算法算出的每一种结果都是对的,然后我就将所有概率换成了根节点。经过多次的结果验证,发现每个图都符合最优二叉树查找的规律,经过仔细的思考我终于理解了:因为查找的键值是根据根节点,而不是根据概率,而且每个键值都是升序。就像跟几点是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
对应最优二叉查找树: