我构建了二进制搜索树:
import random
class Node(object):
def __init__(self, key):
self.key = key
self.leftChild = None
self.rightChild = None
self.parent = None
def hasLeftChild(self):
if self.leftChild:
return True
else:
return False
def hasRightChild(self):
if self.rightChild:
return True
else:
return False
def isLeftChild(self):
if self.parent.leftChild == self:
return True
else:
return False
def isRightChild(self):
if self.parent.rightChild == self:
return True
else:
return False
def isRoot(self):
if not self.parent:
return True
else:
return False
class BinaryTree(object):
def __init__(self):
self.root = None
self.storage = 0
def addNode(self, newItem):
if self.storage == 0:
self.root = Node(newItem)
else:
currentNode = self.root
self.__addNode(currentNode, newItem)
self.storage += 1
def __addNode(self, currentNode, newItem):
if newItem < currentNode.key:
if currentNode.hasLeftChild():
self.__addNode(currentNode.leftChild, newItem)
else:
currentNode.leftChild = Node(newItem)
currentNode.leftChild.parent = currentNode
if newItem > currentNode.key:
if currentNode.hasRightChild():
self.__addNode(currentNode.rightChild, newItem)
else:
currentNode.rightChild = Node(newItem)
currentNode.rightChild.parent = self
def findNode(self, searchKey):
if self.storage == 0:
return None
else:
if self.root.key == searchKey:
return self.root
else:
currentNode = self.root
return self.__findNode(currentNode, searchKey)
def __findNode(self, currentNode, searchKey):
if searchKey == currentNode.key:
return currentNode
if searchKey < currentNode.key:
if currentNode.hasLeftChild():
return self.__findNode(currentNode.leftChild, searchKey)
if searchKey > currentNode.key:
if currentNode.hasRightChild():
return self.__findNode(currentNode.rightCHild, searchKey)
return None
def getRandomNode(self):
randomNum = random.randrange(self.storage)
currentNode = self.root
self.__getRandomNode(currentNode, randomNum)
def __getRandomNode(self, currentNode, numCount):
if numCount == 0:
print('Find node {0}'.format(currentNode.key))
return currentNode, numCount
else:
if currentNode.hasLeftChild():
numCount -= 1
node, numCount = self.__getRandomNode(currentNode.leftChild, numCount)
if currentNode.hasRightChild():
numCount -= 1
node, numCount = self.__getRandomNode(currentNode.rightChild, numCount)
return None, numCount
print('-----Add Node to BTree-----')
myBinaryTree = BinaryTree()
myBinaryTree.addNode(15)
myBinaryTree.addNode(10)
myBinaryTree.addNode(20)
myBinaryTree.addNode(9)
myBinaryTree.addNode(13)
myBinaryTree.addNode(12)
print('-----Get Random Node-----')
myBinaryTree.getRandomNode()
当我构建getRandom递归函数时,由于某些原因,我只能打印(使查找随机节点在逻辑上起作用)。但这不是我的主要目的,我的主要目的是返回&#34;随机节点&#34; 任何人都可以帮我修改getRandom函数并让&#34;返回Node&#34;真的有用吗?
谢谢
答案 0 :(得分:0)
我会将所有节点放在一个列表中,然后在[0;长度 - 1]并采取该节点
因此,另一种算法在每个节点上都需要一个size属性,该节点是以节点为根的子树的大小。
示例:
/ - 2
1
\ - 3 - 4
1的节点的大小是4,2的节点的大小是1,3的节点的大小是2,4的节点的大小是1
以下是算法:
def findNthNode(currentNode, nth):
if currentNode == None:
return None
leftSize = 0
if currentNode.hasLeftChild():
leftSize = currentNode.leftChild.size
if nth == leftSize + 1:
return currentNode
elif nth < leftSize + 1:
return findNthNode(currentNode.leftChild, nth)
else:
return findNthNode(currentNode.rightChild, nth - leftSize - 1)
当然,你可以使用一个返回树大小的函数,但效率会低一些。
它是如何运作的?
如果没有当前节点,我们超出界限=&gt;返回无。
如果没有左子,则左子树的大小为0.
如果我们想要的nthNode等于leftSize + 1,则意味着我们找到了我们想要的节点,因此我们返回它。
如果我们想要的nthNode小于leftSize + 1,则意味着nthNode在left子节点内。我们不必更改nthNode,因为右子节点位于nthNode之后。
如果我们想要的nthNode大于leftSize + 1,则意味着nthNode在右子节点内。但是我们必须删除leftSize + 1,因为我们从左边删除了所有节点,这些节点改变了nthNode之前的节点数。
我希望你理解这个算法,因为它有点难以解释
编辑:我完全忘记了,这个算法没有给你带有preorder遍历的nthNode,但实际上是第n个最大的节点,希望它仍然适合你的需求
我已经研究过了,我刚刚找到了一个解决前序遍历的解决方案:
def findNthNode(currentNode, nth):
if currentNode == None:
return None
leftSize = 0
if currentNode.hasLeftChild():
leftSize = currentNode.leftChild.size
if nth == 1:
return currentNode
elif nth <= leftSize + 1:
return findNthNode(currentNode.leftChild, nth - 1)
else:
return findNthNode(currentNode.rightChild, nth - leftSize - 1)
只有三处修改:
在if上,检查nth == 1,因为第一个元素是前序遍历中的根。
关于elif:
你做了nth - 1,因为你经历了前序遍历中的根
你做&lt; =而不是&lt;因为你用它计算根
答案 1 :(得分:0)
需要更改节点类:
class Node(object):
def __init__(self, key):
self.key = key
self.leftChild = None
self.rightChild = None
self.parent = None
self.size = 0
BinaryTree类中的addNode函数需要更改:
def addNode(self, newItem):
if self.storage == 0:
self.root = Node(newItem)
self.root.size = 1
else:
currentNode = self.root
self.__addNode(currentNode, newItem)
self.storage += 1
def __addNode(self, currentNode, newItem):
if newItem < currentNode.key:
if currentNode.hasLeftChild():
self.__addNode(currentNode.leftChild, newItem)
else:
currentNode.leftChild = Node(newItem)
currentNode.leftChild.parent = currentNode
currentNode.leftChild.size = 1
self.updateNodeSize(currentNode.leftChild)
if newItem > currentNode.key:
if currentNode.hasRightChild():
self.__addNode(currentNode.rightChild, newItem)
else:
currentNode.rightChild = Node(newItem)
currentNode.rightChild.parent = currentNode
currentNode.rightChild.size = 1
self.updateNodeSize(currentNode.rightChild)
另外,每次插入后都需要添加新功能:
def updateNodeSize(self, currentNode):
if not currentNode.isRoot():
currentNode.parent.size += 1
self.updateNodeSize(currentNode.parent)
如果你有BinaryTree Class的删除功能,你还需要在每次删除后为更新节点大小编写新函数。 为了从现有树中获取一个随机节点,增加插入和删除的时间复杂度,这可能是我们需要考虑的另一个问号:) 无论如何,相同问题没有“最佳代码”,但“更好的代码”。
答案 2 :(得分:0)
class BinaryTree(object):
def __init__(self):
self.root = None
self.storage = 0
self.toatlCount = 0
self.randomNode = None
对于添加randomNode函数,我们更改为:
def getRandomNode(self):
randomNum = random.randrange(self.storage)
currentNode = self.root
# initial self.randomNode each time
self.randomNode = None
self.__getRandomNode(currentNode, randomNum)
return self.randomNode
def __getRandomNode(self, currentNode, numCount):
if self.toatlCount == numCount:
self.randomNode = currentNode
else:
if currentNode.hasLeftChild():
self.toatlCount += 1
self.__getRandomNode(currentNode.leftChild, numCount)
if currentNode.hasRightChild():
self.toatlCount += 1
self.__getRandomNode(currentNode.rightChild, numCount)
return None
基于此解决方案,您将始终获得基于匹配条件的最后一个递归节点。