【问题标题】:How to calculate balance of AVL-Tree node recursively and in a single function? (Python)如何在单个函数中递归计算 AVL-Tree 节点的余额? (Python)
【发布时间】:2020-12-03 11:23:16
【问题描述】:

这里的第一个问题,所以如果我遗漏了一些重要的事情,请告诉我。 我有一个平衡的 AVL 树,我需要创建一个可以计算单个给定节点的平衡的函数。这需要在单个函数中递归进行。 (顺便说一下,这是用 Python 编写的)

我还包括了Node类的实例化方法,这样你就可以看到节点的属性。 到目前为止,我已经想出了这个,虽然它有效,但它仍然不符合标准:

class Node: 
    def __init__(self, value, root): 
        self.value = value # Node value
        self.left = None # Left child
        self.right = None # Right child
        self.root = root # Stores the original root of the tree

    def getBalance(self, node):
        return self.getTreeHeight(node.right)-self.getTreeHeight(node.left)
        
    def getTreeHeight(self, rootnode):
        if rootnode == None:
            return -1
        else: 
            return max(self.getTreeHeight(rootnode.left), self.getTreeHeight(rootnode.right)) + 1    

任何提示将不胜感激。 我所需要的只是朝着正确的方向轻推,因为老实说,我有点难过。

提前谢谢你!

【问题讨论】:

  • 平衡的概念不是归纳的:当你知道一个节点的两个孩子的平衡时,你不能从那个信息中推导出节点本身的平衡。因此,如果解决方案需要使用递归,那么该递归将不仅仅是平衡。你不能希望创建一个 getBalance 可以通过递归调用自身来完成这项工作。它要么需要返回的不仅仅是余额(如高度),要么依赖于另一个使用递归的函数。
  • 为什么你的方法需要node 参数?你肯定会在节点上调用这些方法你希望他们提供信息,那么为什么你还需要这个参数呢?

标签: python tree binary-tree avl-tree


【解决方案1】:

首先是关于您的实现的一些通用 cmets:

  • 为每个节点提供一个指向树根的指针是不常见的。如果您决定在树的顶部添加一个新节点,使当前根成为新节点的子节点,这是非常不切实际的。然后你必须访问 每个 节点来更新对根的引用。

  • 这两种方法都以一个节点为参数,但很遗憾,因为self已经是一个节点,所以那个节点可能是操作的主题。这需要对getTreeHeight 进行细微更改,因为您当前允许参数为None。但最终最好让这些方法在没有参数的情况下工作(self 除外)。

现在问题。不可能编写一个只调用自己并且不传递或返回任何额外信息的getBalance 方法。这是因为平衡的概念不是归纳的:如果你知道给定节点的子节点的平衡,那么这个信息对于确定节点本身的平衡是没有用的。所以你需要以某种方式传递一些额外的信息。

一种方法是向getBalance 添加一个可选参数,该参数将指示函数是否被递归调用。如果递归,它可以返回高度,如果不是,则返回余额。这样你实际上合并了你已经编写的两个函数:

def getBalance(self, recurring=False):
    left = self.left.getBalance(True) if self.left else 0
    right = self.right.getBalance(True) if self.right else 0
    return max(left, right) + 1 if recurring else right - left

调用为:

node = root.left.right.right  # get a reference to some node in your tree
balance = node.getBalance()  # get the balance of that node (no argument!)

【讨论】:

  • 感谢您的洞察力,这很有帮助!关于节点作为参数,确实没必要,可惜我收到了部分写的代码,不允许更改,所以作为参数的节点只好留下,其他一些方法就是这样调用的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-18
  • 2013-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-18
相关资源
最近更新 更多