python实现最优二叉搜索树(OBST)

"""
实现最优二叉搜索树
p_i为关键字 k_i概率,q_i为空节点概率,
e[i, j]为从顶点 k_i到 k_j组成的最优二叉搜索树的均值
w[i, j] = (p_i + p_i+1 + ... + p_j) + (q_i-1 + q_i + ... + q_j)

1、j = i - 1时
    e[i, j] = q_i-1
2、j >= i 时
    e[i, j] = e[i, r-1] + e[r+1, j] + w[i, j],
    (其中,w[i, j] = w[i, r-1] + p_r + w[r+1, j]
                   = w[i, j-1] + p_j + q_j)

"""
"""
实现最优二叉搜索树(OptimalBinarySearchTree(OBST))
    可打印出期望代价表e,权重表w,根节点表root
"""
def OBST(p, q, n, e, w, root):
    for i in range(1, n+2):
        e[i][i-1] = q[i-1]                                      # 当根为k_1, ..., k_n时将e和w的对角线赋值为空结点q[i-1]权重
        w[i][i-1] = q[i-1]                                      # w[i][j] = p_i + ... + p_j + q_i-1 + ... + q_j

    for l in range(1, n+1):
        for i in range(1, n - l + 2):                           # 只用下标为1到n+1行,下表为0的行不用
            j = i + l - 1                                       # 下标为0到n列
            e[i][j] = float("inf")                              # 初始化e[i][j]为正无穷
            w[i][j] = round(w[i][j-1] + p[j] + q[j], 2)         # 计算w[i][j],保留2位数,不保留的话会出现异常数据
            for r in range(i, j+1):                             # 根结点取1到n
                t = round(e[i][r-1] + e[r+1][j] + w[i][j], 2)
                if t < e[i][j]:                                 # 将e[i][j]更新到最小
                    e[i][j] = t
                    root[i][j] = r                              # 将e[i][j]为最小时的根节点保存为root[i][j]

    print("期望搜索代价表e:")
    for i in range(1, n+2):                                     # 打印行号1到n+1行,第0行没用到不打印
        print(e[i][:])

    print("权重表w:")
    for i in range(1, n+2):                                     # 打印行号1到n+1行,第0行没用到不打印
        print(w[i][:])

    print("根节点表root:")                                       # 打印行号1到n行,第0行和第0列没用到不打印
    for i in range(1, n+1):
        print((root[i][1:]))

p = [0, 0.15, 0.10, 0.05, 0.10, 0.20]                           # 查找成功结点权重,共6个节点,第一个节点概率为0,实际共5个结点
q = [0.05, 0.10, 0.05, 0.05, 0.05, 0.10]                        # 查找失败结点权重
n = len(p) - 1                                                  # 共5个节点
e, w, root = [], [], []                                         # 将e, w, root定义为一维数组
for i in range(n+2):                                            # 将e, w, root初始化为全0的7行6列的二维数组,行号为0在函数中用不到,但也要生成,否则会出现溢出错误
    e.append([0]*(n+1))                                         #在一维数组e中添加一维数组[0, 0, 0, 0, 0, 0],变为二维数组
    root.append([0]*(n+1))
    w.append([0]*(n+1))

OBST(p, q, n, e, w, root)

 运行结果:

期望搜索代价表e:
[0.05, 0.45, 0.9, 1.25, 1.75, 2.75]
[0, 0.1, 0.4, 0.7, 1.2, 2.0]
[0, 0, 0.05, 0.25, 0.6, 1.3]
[0, 0, 0, 0.05, 0.3, 0.9]
[0, 0, 0, 0, 0.05, 0.5]
[0, 0, 0, 0, 0, 0.1]
权重表w:
[0.05, 0.3, 0.45, 0.55, 0.7, 1.0]
[0, 0.1, 0.25, 0.35, 0.5, 0.8]
[0, 0, 0.05, 0.15, 0.3, 0.6]
[0, 0, 0, 0.05, 0.2, 0.5]
[0, 0, 0, 0, 0.05, 0.35]
[0, 0, 0, 0, 0, 0.1]
根节点表root:
[1, 1, 2, 2, 2]
[0, 2, 2, 2, 4]
[0, 0, 3, 4, 5]
[0, 0, 0, 4, 5]
[0, 0, 0, 0, 5]

Process finished with exit code 0

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值