【问题标题】:BST, finding next highest nodeBST,寻找下一个最高节点
【发布时间】:2014-01-08 08:50:56
【问题描述】:

在 BST 中,根据 Programming Interviews Exposed

“给定一个节点,你甚至可以在 O(log(n)) 时间内找到下一个最高节点”第 65 页

BST 中的一个节点有右孩子作为下一个最高节点,那么为什么 O(log(n))?请指正

先回答,再否定

【问题讨论】:

  • 如果没有合适的孩子怎么办?
  • 你认为下一个最高节点是什么意思?
  • 可能是下一个更大/更大的节点。
  • 那么,我不知道..可能有很多情况,你否定了这个问题吗?

标签: data-structures tree


【解决方案1】:

关于您的评论“BST 中的节点有右子节点作为下一个最高节点”(假设这里“下一个最高”表示下一个顺序值) - 不,它没有。

如果右孩子没有左子树,可能就是这种情况,但并非总是如此。

下一个顺序值(我使用该术语而不是“最高”,因为后者可能与树高混淆,而“最大”意味着 特定(从低到高)顺序而不是 any order) 值来自两个地方之一。


首先,如果当前节点有一个右孩子,移动到那个右孩子然后,只要你能看到一个左孩子,就移动到它。

换句话说,以SD 作为源(当前)和目标(第二大):

   S
  / \
 x   x <- This is the node your explanation chose,
    / \    but it's the wrong one in this case.
   x   x
  /
 D <----- This is the actual node you want.
  \
   x

否则(即如果当前节点有没有右孩子),你需要不断向上移动到父节点(所以节点需要一个右、左和父指针)直到你移动的节点from 是一个左孩子。如果您到达根节点并且仍然没有从左孩子向上移动,那么您的原始节点已经是树中的最高节点。

以图形方式说明整个过程:

x
 \
  D <- Walking up the tree until you came up
 / \     from a left node.
x   x
 \
  x
 / \
x   S
   /
  x

此类函数的伪代码(涵盖这两种情况)将是:

def getNextNode (node):
    # Case 1: right once then left many.

    if node.right != NULL:
        node = node.right
        while node.left != NULL:
            node = node.left
        return node

    # Case 2: up until we come from left.

    while node.parent != NULL:
        if node.parent.left == node:
            return node.parent
        node = node.parent

    # Case 3: we never came from left, no next node.

    return NULL

由于努力与树的高度成正比(我们要么向下,要么向上然后向下),一个平衡树的时间复杂度为O(log N),因为高度有一个logN 与项目数的关系。

这本书在这里讨论的是平衡树,因为它包含了关于它们的如下 sn-ps:

  • 此查找是一种快速操作,因为您在每次迭代中从搜索中消除了一半的节点。
  • 查找是二叉搜索树中的O(log(n)) 操作。
  • 如果您能保证每次迭代中剩余待搜索的节点数减半或接近减半,则仅查找 O(log(n))

因此,虽然它在最后的引用中承认 BST 可能是平衡的,但O(log N) 属性仅适用于那些是的变体。

对于非平衡树,复杂度(最坏情况)为O(n),因为您最终可能会得到如下退化树:

S             D
 \           /
  x         x
   \         \
    x         x
     \         \
      x         x
       \         \
        x         x
       /           \
      D             S

【讨论】:

  • log(n) 怎么样?
  • @user2901020 在平衡树中,depth 为 O(log N)。在寻找下一个节点时,您最多向上走 depth 次,然后最多向下走 depth 次 - 求和时会导致 O(log N)。
  • 实现它,你如何找到给定节点的父节点,没有反向指针对吗?简而言之,你能告诉我这是如何实现的吗,对我来说,它如下所示,首先计算源节点的深度,然后计算其父节点,然后检查源节点是它的右节点还是左节点..我是迷茫了,你能给我一个正确的方向吗?
  • @user2901020,最简单的方法是在每个节点中都有一个父指针。我将为该函数添加一些伪代码。
  • 我同意你的解决方案,但是这样你正在修改节点本身,如果没有可用空间来存储父指针,你的方法是什么..
【解决方案2】:

我认为,我们可以通过简单地找到节点的 Inorder Successor 来找到下一个最高节点。

步骤-

  • 首先,转到节点的右子节点。
  • 然后尽可能向左移动。当您到达叶节点时,打印该叶节点,因为与给定节点相比,该节点是您的下一个最高节点。

【讨论】:

    【解决方案3】:

    这是我在 Java 中的伪实现。希望对您有所帮助。

    节点结构

    public Class Node{
    
    int value {get, set};
    Node leftChild {get,set};
    Node rightChild{get, set};
    Node parent{get,set};
    }
    

    查找下一个最高节点的功能

    public Node findNextBiggest(Node n){
        Node temp=n;
        if(n.getRightChild()==null)
        {
            while(n.getParent()!=null && temp.getValue()>n.getParent().getValue())
            {
                n=n.getParent():
            }
            return n.getParent();
        }
        else
        {
            n=n.getRightChild();
            while (n.getLeftChild()!=null && n.getLeftChild().getValue()>temp.getValue())
            {
                n=n.getLeftChild();
            }
        return n;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-02-29
      • 2016-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多