算法设计第五次作业part2

1.纸面题:对最优二叉树和矩阵连乘两种算法验证四边形法则,如果符合四边形法则则举几个正例,如果不符合则举几个反例

四边形法则

i<i‘j<j‘w(i,j)+w(i‘,j‘)≤w(i‘,j)+w(i,j‘)i < i^`\ \ \ j < j^` \\ w(i,j) + w(i^`,j^`) \le w(i^`,j) + w(i,j^`) i<i‘   j<j‘w(i,j)+w(i‘,j‘)≤w(i‘,j)+w(i,j‘)

最优二叉树

符合四边形法则,举正例

对于如下输入

节点概率表

节点 p1 p2 p3 p4 p5
概率 0.15 0.10 0.05 0.10 0.20

伪节点概率表

节点 (-无穷, p1) (p1,p2) (p2,p3) (p3,p4) (p4,p5) (p5, 无穷)
概率 0.05 0.1 0.05 0.05 0.05 0.1

根据最优二叉搜索树算法,可以得出如下的二维矩阵e[i][j]

e[i][j]表示包含关键字ki ... kj的最优二叉搜索树进行一次搜索的期望代价,最终希望计算出 e[0][n]

0.05 0.45 0.90 1.25 1.75 2.75
0 0.10 0.40 0.70 1.20 2.00
0 0 0.05 0.25 0.60 1.30
0 0 0 0.05 0.30 0.90
0 0 0 0 0.05 0.05
0 0 0 0 0 0.10

可以看到:
e[0][4]+e[1][5]≤e[0][5]+e[1][4]1.75+2.00≤1.20+2.75e[0][4] + e[1][5] \le e[0][5] + e[1][4]\\ 1.75 + 2.00 \le 1.20 + 2.75 e[0][4]+e[1][5]≤e[0][5]+e[1][4]1.75+2.00≤1.20+2.75
矩阵中其他非0元素,皆满足:
e[i][j]+e[i‘][j‘]≤e[i][j‘]+e[i‘][j]e[i][j] + e[i^`][j^`] \le e[i][j^`] + e[i^`][j] e[i][j]+e[i‘][j‘]≤e[i][j‘]+e[i‘][j]
则满足四边形法则

矩阵连乘

不满足,则举反例

现有如下矩阵列表:

A1 A2 A3 A4 A5 A6
30X35 35X15 15X5 5X10 10X20 2025

根据矩阵练乘动态规划算法,可以得出如下的备忘录m[i][j]

0 15750 7875 9375 11875 15125
0 2625 4375 7125 10500
0 750 2500 5375
0 1000 3500
0 5000
0

其中可以看到:
m[0][2]+m[1][3]=7875+4375=12250m[1][2]+m[0][3]=2625+9375=12000m[0][2] + m[1][3] = 7875 + 4375 = 12250\\ m[1][2] + m[0][3] = 2625 + 9375 = 12000\\ m[0][2]+m[1][3]=7875+4375=12250m[1][2]+m[0][3]=2625+9375=12000
即:
m[0][2]+m[1][3]>m[1][2]+m[0][3]m[0][2] + m[1][3] > m[1][2] + m[0][3] m[0][2]+m[1][3]>m[1][2]+m[0][3]
不符合四边形法则的不等式定义。

2.编程实现最优二叉搜索树,输入输出自己定义。

package mainimport ("fmt""math"
)/**
编程实现最优二叉搜索树,输入输出自己定义
*/// 节点
type BSTNode struct {name        string // 节点名left, right *BSTNode
}// 创建二维数组
func makeFloat2DimensionArray(row, column int) [][]float64 {result := make([][]float64, row)for i := 0; i < row; i++ {temp := make([]float64, column)result[i] = append(result[i], temp...)}return result
}
func makeInt2DimensionArray(row, column int) [][]int {result := make([][]int, row)for i := 0; i < row; i++ {temp := make([]int, column)result[i] = append(result[i], temp...)}return result
}func optimalBST(pList, qList []float64, n int) ([][]float64, [][]int) {// e[i,j] 表示包含关键字 ki ... kj 的最优二叉搜索树进行一次搜索的期望代价,最终希望计算出 e[1,n]e := makeFloat2DimensionArray(n+2, n+1)// w[i,j] 表示对于包含关键字 ki ... kj 的子树,所有的概率之和w := makeFloat2DimensionArray(n+2, n+1)// root[i,j] 表示包含关键字 ki ... kj 的子树的根root := makeInt2DimensionArray(n+1, n+1)for i := 1; i <= n+1; i++ {e[i][i-1] = qList[i-1]w[i][i-1] = qList[i-1]}for l := 1; l <= n; l++ {for i := 1; i <= n-l+1; i++ {j := i + l - 1e[i][j] = math.MaxFloat64w[i][j] = w[i][j-1] + pList[j] + qList[j]// 算法改进:动态规划加速if i < j {for r := root[i][j-1]; r <= root[i+1][j]; r++ {t := e[i][r-1] + e[r+1][j] + w[i][j]if t < e[i][j] {e[i][j] = troot[i][j] = r}}} else {e[i][j] = e[i][j-1] + e[i+1][j] + w[i][j]root[i][j] = i}}}return e, root
}// 打印 最优二叉搜索树
func makeBST(i, j int, root [][]int) {fmt.Printf("p%d 为 根\n", root[i][j])printBST(i, j, root)
}func printBST(i, j int, root [][]int) {if i <= j {r := root[i][j]if r > i {c := root[i][r-1]fmt.Printf("p%d 为 p%d 的左孩子\n", c, r)printBST(i, r-1, root)} else {fmt.Printf("q%d 为 p%d 的左孩子\n", r-1, r)}if r < j {c := root[r+1][j]fmt.Printf("p%d 为 p%d 的右孩子\n", c, r)printBST(r+1, j, root)} else {fmt.Printf("q%d 为 p%d 的左孩子\n", r+1, r)}}
}func main() {// 节点概率 0 表示无此节点pList := []float64{0, 0.15, 0.10, 0.05, 0.10, 0.20}// 区间概率qList := []float64{0.05, 0.1, 0.05, 0.05, 0.05, 0.1}e, root := optimalBST(pList, qList, 5)fmt.Printf("最优二叉搜索树总概率:%.2f \n", e[1][5])makeBST(1, 5, root)
}

输入

节点概率表

节点 p1 p2 p3 p4 p5
概率 0.15 0.10 0.05 0.10 0.20

伪节点概率表

节点 (-无穷, p1) (p1,p2) (p2,p3) (p3,p4) (p4,p5) (p5, 无穷)
概率 0.05 0.1 0.05 0.05 0.05 0.1

输出

总结

该算法为典型的动态规划算法,其中包含多个表进行递推。

  • e[i][j]表示包含节点k1 ... kj所组成的最优二叉搜索树进行一次搜索的期望,最终需要得到e[1][n]
  • w[i][j]表示包含节点k1 ... kj的概率之和
  • root[i][j]表示包含节点k1 ... kj所组成的最优二叉搜索树的根

则可以列出关于 e[i][j] 的递推式和边界条件:
e[i][j]={qi−1(j=i−1)mini≤r≤j(e[i,r−1]+e[r+1][j]+w[i,j])(i≤j)e[i][j] = \begin{cases} q_{i-1} \ \ (j = i -1)\\ min_{i \le r \le j}(e[i,r-1]+e[r+1][j]+w[i,j]) \ \ (i \le j) \end{cases} \\ e[i][j]={qi−1​  (j=i−1)mini≤r≤j​(e[i,r−1]+e[r+1][j]+w[i,j])  (i≤j)​
其中边界条件指,子树只包含伪关键字q[i-1];递推式则表示,当以 r 为根节点时,求出最小的期望值e[i][j]

而递推式的推导过程如下:

当将左右子树分别连接根节点 r 后,其概率都根据深度+1 而翻倍,即添加对应的w[i][j],则可根据定义得:
e[i][j]=pr+(e[i][r−1]+w[i][r−1])+(e[r+1][j]+w[r+1][j])其中(e[i][r−1]+w[i][r−1])为左子树,(e[r+1][j]+w[r+1][j])为右子树e[i][j] = p_r + (e[i][r-1] + w[i][r-1]) + (e[r+1][j] + w[r+1][j])\\ 其中(e[i][r-1] + w[i][r-1]) 为左子树,(e[r+1][j] + w[r+1][j])为右子树 e[i][j]=pr​+(e[i][r−1]+w[i][r−1])+(e[r+1][j]+w[r+1][j])其中(e[i][r−1]+w[i][r−1])为左子树,(e[r+1][j]+w[r+1][j])为右子树
而:
w[i][j]=pr+w[i][r−1]+w[r+1][j]w[i][j] = p_r + w[i][r-1] + w[r+1][j] w[i][j]=pr​+w[i][r−1]+w[r+1][j]
故可以化简得:
e[i][j]=e[i][r−1]+e[r+1][j]+w[i][j]e[i][j] = e[i][r-1] + e[r+1][j] + w[i][j] e[i][j]=e[i][r−1]+e[r+1][j]+w[i][j]
类似得,可以得出关于 w[i][j] 的递推式:
w[i][j]={qi−1(j=i−1)w[i][j−1]+p[j]+q[j](i≤j)w[i][j] = \begin{cases} q_{i-1} \ \ (j = i -1)\\ w[i][j-1] + p[j] + q[j] \ \ (i \le j) \end{cases} w[i][j]={qi−1​  (j=i−1)w[i][j−1]+p[j]+q[j]  (i≤j)​
root[i][j] 则与概率计算无关,主要用于回头构造二叉树时所用。

算法:最优二叉搜索树相关推荐

  1. 最优二叉搜索树(Optimal BST)-算法导论

    问题描述: 维基百科定义: https://en.wikipedia.org/wiki/Optimal_binary_search_tree In the static optimality prob ...

  2. 算法导论 — 15.5 最优二叉搜索树

    ###笔记 二叉搜索树满足如下性质:假设xxx是二叉搜索树中的一个结点.如果lll是xxx的左子树的一个结点,那么l.key≤x.keyl.key ≤ x.keyl.key≤x.key.如果rrr是x ...

  3. 《算法导论》15.5 最优二叉搜索树(含C++代码)

    一.问题背景和描述 给定一个n个不同关键字的已排序的序列K=<k1,k2, - kn>(因此k1<k2<-<kn),我们希望用这 些关键字构造一棵二叉搜索树.对每个关键字 ...

  4. 【算法设计与分析】动态规划:最优二叉搜索树

    最优二叉搜索树问题的问题提出是,设S={x1, x2, -, xn}是一个由n个关键字组成的线性有序集,(a0, b1, a1, -, bn, an) 为集合S的存取概率分布,表示有序集S的二叉搜索树 ...

  5. 动态规划最优二叉搜索树C语言,算法 – 动态规划:最优二叉搜索树

    好吧,我希望有人可以向我解释一下.我正在攻读决赛,我无法解决问题. 问题是动态编程;构造最优二叉搜索树(OBST).我理解一般的动态编程和特别是这个问题的概念,但我不明白这个问题的递归形式. 我得到的 ...

  6. 算法实验 最优二叉搜索树

    最优二叉搜索树 最优二叉搜索树 问题描述 问题分析 代码 问题描述 二叉搜索树我们都知道,左子树结点的值都小于根结点,右子树结点的值都大于根节点.如果某个结点没有左子树或右子树,那么在对应的位置上加一 ...

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

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

  8. 算法设计与分析--最优二叉搜索树(Python)

    最优二叉搜索树: 给定一个n个不同关键字的已排序的序列K=<k1,k2,-,kn>(因此k1<k2<-<kn)我们希望用这些关键字构造一棵二叉树.对每个关键字ki,都有一 ...

  9. 最优二叉搜索树探究【C/C++】

    简述 什么是二叉树 下面的这棵树,就是二叉搜索树 相对于什么最优 这里考虑的是ASL(average search length)平均搜索长度.即根据概率来生成ASL最小的搜索树. 到这里,最优二叉搜 ...

最新文章

  1. VS Code – No source control providers 解决方法
  2. VC++ CopyFile函数使用方法
  3. 杭电1867 A + B for you again
  4. 设置UserAgent让电脑浏览器访问微信手机网站
  5. java 传入参数_Java 中方法参数的传递
  6. spark中各种数量的确定和查询(持续更新中)
  7. 单路电压表c语言编程,用AT89C51单片机制作的数字电压表
  8. python:对list去重
  9. html5白话解释,HTML5这个词到底是什么意思?
  10. 程序架构探讨—001 多段select语句的方案
  11. bazel 链接第三方动态库_C/C++编程知识:Linux 动态库相关知识整理
  12. 考研数据结构之栈(2.5)——练习题之求解二次方根A的迭代函数,写出相应的递归算法和非递归算法(C表示)
  13. C++ Primer Message和Folder类
  14. 鼠标悬停放大图片特效
  15. 象棋巫师魔法学校/象棋路边摊 前1050关
  16. “工程化”对于大型数据平台而言,意味着什么?StartDT Hackathon来了
  17. 【luminate primordial】苏州之行
  18. AI:华为云HiLens Kit试用测评—全栈全场景的人工智能
  19. 超市结算系统|Springboot+Vue通用超市结算收银系统
  20. 从小镇到北大!再到阿里达摩院,「AI萝莉」的“升级打怪”之路...

热门文章

  1. 火猫tv直播精灵 v1.1.1 官方版​
  2. excel如何一键多姿势
  3. python 进行图片的文字识别
  4. 16.div+css实战五 阿里云src响应中心底部制作
  5. 数据集2020(一)GraspNet-1Billion: A Large-Scale Benchmark for General Object Grasping
  6. 【LeetCode】树的子结构二叉树的镜像对称的二叉树
  7. 安装系统之四 U盘装GHOST XP教程
  8. 浪花淘尽英雄 --《浪潮之巅》读书笔记壹
  9. 登录验证过程,PC与APP开放登录接口(支持WEB与SDK方式)
  10. 联咏NT9833xSDK编译