二分检索树T是一棵二元树
①T的左子树的所有元素比根结点中的元素小;
②T的右子树的所有元素比根结点中的元素大;
③T的左子树和右子树也是二分检索树
研究问题:最优二分检索树,求一棵预期成本最小的二分检索树
二叉搜索树的叶结点是形如(Xi, Xi+1)的开区间。在表示S的二叉搜索树中搜索元素x,返回的结果不外乎两种:
- 在二叉搜索树的内结点中找到x=xi
- 在二叉搜索树的叶结点中确定x∈(Xi, Xi+1)
最优二叉搜索树问题时对有序集S及其存取概率分布(a0,b1,a1, ...,bn, an), 在所有表示有序集S的二叉搜索树中找出一颗具有最小平均路长的二叉搜索树。
import numpy as np
print("最优二叉搜索树 自底向上非递归的动态规划算法")
n = 5 # 节点个数
p = [0, 0.1, 0.3, 0.1, 0.2, 0.1] # 节点查找成功的概率
q = [0, 0.04, 0.02, 0.05, 0.05, 0.06, 0.01] # 节点查找失败的概率
w = np.zeros((n + 2, n + 2))
root = np.zeros((n + 2, n + 2))
e = np.zeros((n + 2, n + 2))
'''
n; // 根节点数
p; // 查找 关键字 的概率
q; // 查找 虚拟键 的概率
root; // 根节点
w; // 子树概率总和
e; // e[i,j]包含关键字ki,...kj的最优二叉搜索树种进行一次搜索的期望代价
'''
def OptimalBST(n, p, q, root, w, e):
# 处理w[i, j]和e[i, j]中i = j + 1的情况,这种情况都是q[i - 1]
for i in range(1, n + 2):
w[i][i - 1] = q[i - 1]
e[i][i - 1] = 0
i, j, r = 0, 0, 0
temp = 0 # 存放计算得到的临时期望
for l in range(1, n + 1): # 1-5
for i in range(1, n - l + 2): # 1-6
j = l + i - 1
e[i][j] = 999999999
w[i][j] = w[i][j - 1] + p[j] + q[j]
for r in range(i, j + 1):
temp = e[i][r - 1] + e[r + 1][j] + w[i][j]
if temp < e[i][j]:
e[i][j] = temp
root[i][j] = r
def printBT(root, i: int, j: int):
if i < j:
r = root[int(i)][int(j)]
print("s%d是根" % r)
if root[int(i)][int(r - 1)] > 0:
print("s%d的左孩子是s%d" % (r, root[int(i)][int(r - 1)]))
if root[int(r + 1)][int(j)] > 0:
print("s%d的右孩子是s%d" % (r, root[int(r + 1)][int(j)]))
printBT(root, i, r - 1)
printBT(root, r + 1, j)
if __name__ == "__main__":
OptimalBST(n, p, q, root, w, e)
printBT(root, 1, n)
print("-------------root根节点---------------")
print(root)
print("--------------w子树概率总和-----------------")
print(w)
print("-------------e子树期望-----------------")
print(e)
舞台再大,你不上台,永远只是观众。平台再好,你不参与,永远只是局外人。
能力再大,你不行动,只能看别人成功!没有人关心你付出了多少努力,撑的累不累,摔的痛不痛,他们只会看你最后站在什么位置,然后羡慕或摒弃。