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