【问题标题】:Successor and Predecessor - Binary Search Tree (Python)继任者和前任者 - 二叉搜索树 (Python)
【发布时间】:2016-03-17 17:33:24
【问题描述】:

我正在二叉搜索树上尝试这个继任者和前任者。

只是想知道一旦我掌握了后继代码,我可以将其翻转并用于前任代码吗? 我已经对后继者进行了编码,并尝试将其用于前任。 但是,即使我尝试放置其他值,我的输出值也不会改变..

下面是我的代码:

成功

def succ(self, key):
    temp = self.root
    prev = None
    if (temp.right is not None):
        temp  = temp.right
        while (temp.left is not None):
            temp = temp.left
        prev = temp
    elif temp.left is not None:e
        temp = temp.left
        while (temp.right is not None):
            temp = temp.right
        prev = temp
    else:
        return None
    return prev.key

前任

def pred(self, key):
        temp = self.root
        prev = None
        #if right is not none, succ lies in the right sub tree
        if (temp.right is not None):
            temp  = temp.right
            while (temp.left is not None):
                #return the node with the minimum key value
                temp = temp.left
            prev = temp
        #if left not none, succ lies in the right sub tree
        elif temp.left is not None:
            #go right till .right is None
            #return the node with the maximum key value
            temp = temp.left
            while (temp.right is not None):
                temp = temp.right
            prev = temp
        else:
            #no succ
            return None
        return prev.key

    def createTree(self):
        #root
        self.put("F",6)
        #leftSubTree
        self.put("D",4)
        #leftLeftSubTree
        self.put("C",3)
        self.put("B",2)
        self.put("A",1)
        #LeftRightSubTree
        self.put("E",5)
        #RightSubTree
        self.put("I",9)
        #RightLeftSubTree
        self.put("G",7)
        self.put("H",8)
        #RightRightSubTree
        self.put("J",10)

【问题讨论】:

  • 它们都是一样的。你还没有翻转任何东西。
  • 你能提供一个最小的工作示例吗?因为这些是类的一部分。您可以提供类的各个部分(方法 put 和只是类名和简化的 init ...),以便可以尝试代码。

标签: python


【解决方案1】:

要翻转succ 函数并将其转换为pred,您需要将每个left 更改为right,并将每个right 更改为left

def pred(self, key):
    temp = self.root
    prev = None
    if (temp.left is not None):
        temp  = temp.left
        while (temp.right is not None):
            temp = temp.right
        prev = temp
    elif temp.right is not None:
        temp = temp.right
        while (temp.left is not None):
            temp = temp.left
        prev = temp
    else:
        return None
    return prev.key

【讨论】:

  • 我实际上是在尝试将 succ 函数更改为 pred
  • 当我输入 G 时,它打印出来的字母是 E 而不是 F。我也尝试了其他字母,但我得到的输出总是 E
  • 它们是对称的;他们要么都工作,要么都不起作用。如果其中只有一个有效,则问题出在其他地方。
  • pastebin 代码中没有 succpred,而且您在上面发布的代码都不起作用 - 它们都为所有输入生成“G”。
  • @MartinBroadhurst pred 这里的实现似乎不正确。 elif 块将从根中找到右子树的最左边的孩子。你真正想要的是向上遍历树直到你左转。我提供了一个答案,详细解释了这一点。
【解决方案2】:

让我们假设您有一个 BST 节点类,其中包含三个指针/引用:left、right 和 parent,它们对应于给定节点的左子、右子和父。树中唯一具有指向 None 的父节点的节点将是根节点。

我们还假设我们有以下 BST:

       15
     /     \
    9       20
   / \     /  \
  3   10  17   21
 / \    \
1   5   11

BST 属性规定,对于任何给定节点 nn 的左子树中的所有节点都应小于 n ;并且,n的右子树中的所有节点都应该大于n

为了在实现后继函数和前驱函数时更容易,使用辅助函数来查找给定 BST 或 BST 子树的最小和最大节点是很有帮助的。

最低

def bst_minimum(tree):
  minimum = tree
  while minimum is not None:
    minimum = minimum.left
  return minimum

最大

def bst_maximum(tree):
  maximum = tree
  while maximum is not None:
    maximum = maximum.right
  return maximum

对于上面的树示例,这些函数将返回 1 表示最小值和 21 表示最大值。

要查找给定节点的前任,您必须涵盖以下几种情况:

  1. 如果给定节点有左子树,则取该子树的最大值。
  2. 否则,沿着父节点向上移动树,直到您点击“无”或“左转”。

在第二种情况下,如果你点击无,这意味着没有前任。上面树中值为 1 的节点就是这种情况。它将跟随父指针一直经过根节点。

如果有前驱,那么它将是您在树上左转后遇到的第一个父节点。换句话说,它是父节点,其值小于您开始的节点的值。因此,上面的节点 17 将返回值为 15 的根节点。

前任

def bst_predecessor(tree):
  if tree.left is not None:
    return bst_maximum(tree.left)
  parent = tree.parent
  child = tree
  while parent is not None and child is parent.left:
    child = parent
    parent = child.parent
  return parent

由于后继只是对前驱的对称操作,您可以通过翻转各种操作来修改前驱。即:

  1. 您不想检查左子树并找到最大值,而是要检查右树并找到它的最小值。
  2. 否则,跟随父节点直到你不能再(在这种情况下没有继任者),或者你向右转。因此,节点 5 的后继节点将是上面树中的节点 9。

继任者

def bst_successor(tree):
  if tree.right is not None:
    return bst_minimum(tree.right)
  parent = tree.parent
  child = tree
  while parent is not None and child is parent.right:
    child = parent
    parent = child.parent
  return parent

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多