【发布时间】:2021-12-21 03:39:57
【问题描述】:
如何向我的 BST 类添加两个不同的函数来计算给定树中的最小和最大元素?那么 min(self) 函数和 max(self) 函数呢?目前我无法做到这一点,并且感觉这可能与存储整数有关。我下面的 BST 是否能够按原样存储整数?
class BTNode:
def __init__(self,d,l,r):
self.data = d
self.left = l
self.right = r
t1 = BTNode(15,None,None)
t2 = BTNode(51,None,None)
t = BTNode(5,t1,t2)
t1 = BTNode(21,None,None)
t1 = BTNode(42,t1,None)
t2 = BTNode(18,None,None)
t2 = BTNode(8,t1,t2)
t = BTNode(2,t,t2)
def toString(t):
if t == None:
return "None"
st = str(t.data)+" -> ["
st += toString(t.left)+", "
st += toString(t.right)+"]"
return st
print(toString(t))
# 2
# / \
# 5 8
# / \ / \
# 15 51 42 18
# /
# 21
# Depth-First search
def search(t, d):
if t == None: return False
# input("at node: "+str(t.data))
if t.data == d: return True
if search(t.left,d): return True
return search(t.right,d)
print("\ntest search for 42 then 43")
print(search(t,42))
print(search(t,43))
def printElemsDFS(t):
if t == None:
return
print(t.data)
printElemsDFS(t.left)
printElemsDFS(t.right)
print("\nPrint elements DFS")
printElemsDFS(t)
# Depth-First search using a stack (needs the Stack class)
def searchDF(t, d):
s = Stack()
s.push(t)
while s.size() > 0:
ptr = s.pop()
if ptr == None:
continue
print(ptr.data) # not needed, for illustration
if ptr.data == d:
return True
s.push(ptr.right)
s.push(ptr.left)
return False
print("\ntest now searchDF for 42")
print(searchDF(t,42))
print("\ntest now searchDF for 43")
print(searchDF(t,43))
# Breadth-First search (needs the Queue class)
def searchBF(t, d):
q = Queue()
q.enq(t)
while q.size() > 0:
ptr = q.deq()
if ptr == None:
continue
print(ptr.data) # not needed, for illustration
if ptr.data == d:
return True
q.enq(ptr.left)
q.enq(ptr.right)
return False
print("\ntest now searchBF for 42")
print(searchBF(t,42))
print("\ntest now searchBF for 43")
print(searchBF(t,43))
class BTNode:
def __init__(self,d,l,r):
self.data = d
self.left = l
self.right = r
# def updateChild(self, oldChild, newChild):
# if self.left == oldChild:
# self.left = newChild
# elif self.right == oldChild:
# self.right = newChild
# else: raise Exception("updateChild error")
# prints the node and all its children in a string
def __str__(self):
st = str(self.data)+" -> ["
if self.left != None:
st += str(self.left)
else: st += "None"
if self.right != None:
st += ", "+str(self.right)
else: st += ", None"
return st + "]"
class BST:
def __init__(self):
self.root = None
self.size = 0
def __str__(self):
return str(self.root)
def search(self, d):
ptr = self.root
while ptr != None:
if d == ptr.data:
return True
if d < ptr.data:
ptr = ptr.left
else:
ptr = ptr.right
return False
def add(self, d):
if self.root == None:
self.root = BTNode(d,None,None)
else:
ptr = self.root
while True:
if d < ptr.data:
if ptr.left == None:
ptr.left = BTNode(d,None,None)
break
ptr = ptr.left
else:
if ptr.right == None:
ptr.right = BTNode(d,None,None)
break
ptr = ptr.right
self.size += 1
def add(self, d):
if self.root == None:
self.root = BTNode(d,None,None)
else:
self._addRec(d,self.root)
self.size += 1
def _addRec(self,d,ptr):
if d < ptr.data:
if ptr.left == None:
ptr.left = BTNode(d,None,None)
return
return self._addRec(d,ptr.left)
else:
if ptr.right == None:
ptr.right = BTNode(d,None,None)
return
return self._addRec(d,ptr.right)
def count(self, d):
ptr = self.root
count = 0
while ptr != None:
ptr = self._searchNode(ptr,d)
if ptr != None:
count += 1
ptr = ptr.right
return count
def _searchNode(self, ptr, d):
while ptr != None:
if d == ptr.data:
return ptr
if d < ptr.data:
ptr = ptr.left
else:
ptr = ptr.right
return None
def remove(self,d):
if self.root == None: return
if self.root.data == d:
self.size -= 1
return self._removeRoot()
parentPtr = None
ptr = self.root
while ptr != None:
if ptr.data == d:
self.size -= 1
return self._removeNode(ptr,parentPtr)
parentPtr = ptr
if d < ptr.data:
ptr = ptr.left
else:
ptr = ptr.right
# removes the node ptr from the tree
def _removeNode(self, ptr, parentPtr):
# there are 3 cases to consider:
# 1. the node to be removed is a leaf (no children)
if ptr.left == ptr.right == None:
parentPtr.updateChild(ptr,None)
# 2. the node to be removed has exactly one child
elif ptr.left == None:
parentPtr.updateChild(ptr,ptr.right)
elif ptr.right == None:
parentPtr.updateChild(ptr,ptr.left)
# 3. the node to be removed has both children
else:
# find the min node at the right of ptr -- and its parent
parentMinRNode = ptr
minRNode = ptr.right
while minRNode.left != None:
parentMinRNode = minRNode
minRNode = minRNode.left
# replace the data of ptr with that of the min node
ptr.data = minRNode.data
# bypass the min node
parentMinRNode.updateChild(minRNode,minRNode.right)
def _removeRoot(self):
# this is essentially a hack: we are adding a dummy node at
# the root and call the previous method -- it allows us to
# re-use code
parentRoot = BTNode(None,self.root,None)
self._removeNode(self.root,parentRoot)
self.root = parentRoot.left
t = BST()
t.add("cat")
t.add("car")
t.add("cav")
t.add("cat")
t.add("put")
t.add("cart")
t.add("cs")
print(t)
print(t.count("cat"),t.remove("cat"),t.count("cat"),t.size)
print(t)
print(t.count("cat"),t.remove("cat"),t.count("cat"),t.size)
print(t)
print(t.count("put"),t.remove("put"),t.count("put"),t.size)
print(t)
print(t.count("put"),t.remove("put"),t.count("put"),t.size)
print(t)
【问题讨论】:
-
据我所知,二叉搜索树的定义是在左分支上,每个项目都小于节点内容,在右分支上,每个项目都大于或等于。那么,在找到
None然后返回最后一个非None 元素之前,找到最小和最大元素不等于总是向左/向右走吗? -
从数据结构的角度来看,您也希望它为您存储。并假设存储了树的元素,我可以执行 tree.max() 或 tree.minimum() 或 tree.removeAllElements() 来返回值。在我的示例中,我正在尝试向 BST 类添加一个函数,以便我可以返回树的最大值并在树为空时返回 none
-
请注意,您的树不是 BST(它不尊重 BST 的不变量)
-
我必须做些什么才能让这些功能在我的 BST 课程中正常工作?任何可能的方法通常都会发生冲突,因为如果我尝试在我的 BST 类中编写函数,那么我的 BTNode 类中缺少属性,反之亦然。似乎没有一种方法可以锁定现有树的方法,因此 x.max() 或 x.min() 不存储值
-
由于您的“BST”不符合 BST 的不变量,正如@gimix 所指出的,您必须遍历整个树才能找到最小值和最大值。
标签: python max binary-tree binary-search-tree minimum