猜数字不等概排序二叉树

class BSTVertex:
    '''二叉树顶点类'''
    def __init__(self, val, leftChild, rightChild):
        self.val = val
        self.leftChild = leftChild
        self.rightChild = rightChild
    def getVal(self):
        return self.val
    def getLeftChild(self):
        return self.leftChild
    def getRightChild(self):
        return self.rightChild
    def setVal(self, newVal):
        self.val = newVal
    def setLeftChild(self, newLeft):
        self.leftChild = newLeft
    def setRightChild(self, newRight):
        self.rightChild = newRight

class BSTree:
    '''二叉查找树类'''
    def __init__(self, root):
        self.root = root
        self.size = 1 if root else 0
    def lookup(self, cVal):
        return self.__lookupHelper(cVal, self.root)
    def __lookupHelper(self, cVal, cVertex):
        '''查找顶点cVertex下的值cVal'''
        if cVertex == None:
            return False
        elif cVal == cVertex.getVal():
            return True
        elif cVal < cVertex.getVal():
            return self.__lookupHelper(cVal, cVertex.getLeftChild())
        else:
            return self.__lookupHelper(cVal, cVertex.getRightChild())
    def getVertex(self, cVal, cVertex = None):
        '''查找值cVal对应的顶点默认从根找'''
        if cVertex == None:
            cVertex = self.root
        if self.size == 0:#到叶子结点返回None
            return None
        elif cVal == cVertex.getVal():
            return cVertex
        elif cVal < cVertex.getVal():
            return self.getVertex(cVal, cVertex.getLeftChild())
        else:
            return self.getVertex(cVal, cVertex.getRightChild())
    def insert(self, val):
        '''查入值,默认左右子树为None'''
        if self.root == None:
            self.root = BSTVertex(val, None, None)
            self.size += 1
        else:
            self.__insertHelper(val, self.root)
    def __insertHelper(self, val, pred):
        predLeft = pred.getLeftChild()
        predRight = pred.getRightChild()
        if predRight == None and predLeft == None:
            if val < pred.getVal():
                pred.setLeftChild((BSTVertex(val, None, None)))
            else:
                pred.setRightChild((BSTVertex(val, None, None)))
            self.size += 1
        elif val < pred.getVal():
            if predLeft == None:
                pred.setLeftChild((BSTVertex(val, None, None)))
                self.size += 1
            else:
                self.__insertHelper(val, pred.getLeftChild())
        else:
            if predRight == None:
                pred.setRightChild((BSTVertex(val, None, None)))
                self.size += 1
            else:
                self.__insertHelper(val, pred.getRightChild())
    def getsize(self):
        return self.size
    
def optimalBST(keys, prob):
    '''Guess the numbers. Say a number, and I will tell you whether it is big, small, or equal.
    Arguments:
        keys:number
        prob:Probability of each digit
    Return:
        打印猜的顺序二叉树
    '''
    n = len(keys)
    opt = [[0 for i in range(n)] for j in range(n)]
    computeOptRecur(opt, 0, n - 1, prob)
    print("最佳二叉树根表", opt)
    tree = createBSTRecur(None, opt, 0, n -1 , keys)
    print('Minimum average guesses times is',opt[0][n - 1][0])
    printBST(tree.root)
backrecur = 0
def computeOptRecur(opt, left, right, prob):
    '''递归构造二维数组表示的最佳二叉树根表.左右中选概率大的做根,左右概率和再加其中小的概率做新的概率。
    Arguments:
        opt:n*n two-dimensional array
        left:start
        right:end
        prob:probability of each digit
    Return:
        opt:n*n two-dimensional array,opt[0][n-1][0]Minimum number of guesses,
        opt[0][n-1][1] the number guessed
    '''
    global backrecur
    backrecur += 1
    if left == right:
        opt[left][left] = (prob[left], left)
        return
    try:
        #使用memoization存储中间量,不重复计算
        opt[left][right][1]
    except TypeError:
        #遍历每个做根结点的情况
        for r in range(left,right + 1):
            if left <= r - 1:
                #递归左树缩小起始
                computeOptRecur(opt, left, r - 1, prob)
                leftval = opt[left][r - 1]
            else:
                leftval = (0, -1)
            if r + 1 <= right:
                #递归右树
                computeOptRecur(opt, r + 1, right, prob)
                rightval = opt[r + 1][right]
            else:
                rightval = (0, -1)
            if r == left:
                bestval = leftval[0] + rightval[0]
                bestr = r
            elif bestval > leftval[0] + rightval[0]:#后面还有概率更小的情况
                bestr = r#概率大的做根
                bestval = leftval[0] + rightval[0]
        weight = sum(prob[left: right + 1])#左右概率的和
        opt[left][right] = (bestval + weight, bestr)#再加上小的概率做新的概率,左右中选概率大的做根

def createBSTRecur(bst, opt, left, right, keys):
    '''用最优根构建二叉查找树。Build a binary search tree using the optimal root,
    that opt[0][n - 1],and insert the keys to the bst.use the rindex step
    Arguments:
        bst:binary search tree 
        opt:the optimal root list of binary search tree
        left:start
        right:end
        keys:numbers for guess
    Return:
        bst:the best binary search tree
    '''
    if left == right:
        bst.insert(keys[left])
        #print(keys[left],left,right,'the insert vertex')
        return bst
    
    rindex = opt[left][right][1]#
    rnum = keys[rindex]
    if bst == None:
        bst = BSTree(None)
    bst.insert(rnum)
    #print(rnum,left,right,'the insert vertex')
    if left <= rindex - 1:
        bst = createBSTRecur(bst, opt, left, rindex - 1, keys)
    if rindex + 1 <= right:
        bst = createBSTRecur(bst, opt, rindex + 1, right, keys)
    return bst
def printBST(vertex):
    '''Recursive printing of binary search tree.
    the input parameter can be vertex type and tree type.the tree's root member isn't used.
    '''
    left = vertex.leftChild
    right = vertex.rightChild
    if left != None and right != None:
        print('Value =', vertex.val, 'Left =', left.val, 'Right =', right.val)
        printBST(left)
        printBST(right)
    elif left != None and right ==None:
        print('Value =', vertex.val, 'Left =', left.val, 'Right = None')
        printBST(left)
    elif left == None and right !=None:
        print('Value =', vertex.val, 'Left = None', 'Right =', right.val)
        printBST(right)
    else:
        print('Value =', vertex.val, 'Left = None Right = None')    

keys=[14, 20, 31, 34, 45, 46, 700]#待猜数字
pr = [0.19, 0.25, 0.1, 0.2, 0.15, 0.1, 0.01]#相应的概率
optimalBST(keys, pr)
print(‘递归构造二维数组表示的最佳二叉树根表的递归次数:’,backrecur)
最佳二叉树根表
[[(0.19, 0), (0.63, 1), (0.8300000000000001, 1), (1.33, 1), (1.7800000000000002, 1), (2.17, 3), (2.21, 3)],
[0, (0.25, 1), (0.44999999999999996, 1), (0.9500000000000001, 1), (1.3, 3), (1.6, 3), (1.6400000000000001, 3)],
[0, 0, (0.1, 2), (0.4, 3), (0.7000000000000001, 3), (1.0, 3), (1.04, 3)],
[0, 0, 0, (0.2, 3), (0.5, 3), (0.75, 4), (0.78, 4)],
[0, 0, 0, 0, (0.15, 4), (0.35, 4), (0.38, 4)],
[0, 0, 0, 0, 0, (0.1, 5), (0.12, 5)],
[0, 0, 0, 0, 0, 0, (0.01, 6)]]
Minimum average guesses times is 2.21
猜 = 34 Left = 20 Right = 45
猜 = 20 Left = 14 Right = 31
猜 = 14 Left = None Right = None
猜 = 31 Left = None Right = None
猜 = 45 Left = None Right = 46
猜 = 46 Left = None Right = 700
猜 = 700 Left = None Right = None
递归构造二维数组表示的最佳二叉树根表的递归次数: 113

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值