Algorithm 在不使用父指针的情况下查找后续指针

Algorithm 在不使用父指针的情况下查找后续指针,algorithm,binary-search-tree,Algorithm,Binary Search Tree,BST中元素的后继者是元素的后继者,其排序顺序由顺序遍历决定。MIT出版社出版的CLRS算法教科书《算法导论》中介绍了在每个节点都有指向其父节点的指针时查找后续节点 在这里找到后继元素的想法是——如果节点x的右子树是非空的,则x的后继元素是右子树中的最小元素。否则,后继节点是x的最低祖先,其左子节点也是x的祖先,假设节点是其自身的祖先 我们能在不使用父节点指针的情况下找到后续节点吗 有时我们的树节点没有这个指针。我挣扎了几个小时,但无法编写正确的代码 如果无法访问指向父节点的指针,则需要知道父节

BST中元素的后继者是元素的后继者,其排序顺序由顺序遍历决定。MIT出版社出版的CLRS算法教科书《算法导论》中介绍了在每个节点都有指向其父节点的指针时查找后续节点

在这里找到后继元素的想法是——如果节点x的右子树是非空的,则x的后继元素是右子树中的最小元素。否则,后继节点是x的最低祖先,其左子节点也是x的祖先,假设节点是其自身的祖先

我们能在不使用父节点指针的情况下找到后续节点吗


有时我们的树节点没有这个指针。我挣扎了几个小时,但无法编写正确的代码

如果无法访问指向父节点的指针,则需要知道父节点是谁。如果你不知道,你怎么能在树中上升呢?

如果你不能访问指向父节点的指针,那么你需要知道父节点是谁。如果你不知道,你怎么能爬到树上去呢?

这应该可以:

TREE-SUCCESSOR(T, x)
  if right[x] != NIL
    return TREE-MINIMUM(right[x])
  else
    return FIND-TREE-SUCCESSOR(root[T], x, NIL)

FIND-TREE-SUCCESSOR(y, x, c)
  if y = x
    return c
  if key[x] < key[y]
    return FIND-TREE-SUCCESSOR(left[y], x, y)
  else
    return FIND-TREE-SUCCESSOR(right[y], x, c)
FIND-TREE-successiver将我们左转的最后一个节点的候选节点保留在c中

这应该有效:

TREE-SUCCESSOR(T, x)
  if right[x] != NIL
    return TREE-MINIMUM(right[x])
  else
    return FIND-TREE-SUCCESSOR(root[T], x, NIL)

FIND-TREE-SUCCESSOR(y, x, c)
  if y = x
    return c
  if key[x] < key[y]
    return FIND-TREE-SUCCESSOR(left[y], x, y)
  else
    return FIND-TREE-SUCCESSOR(right[y], x, c)

FIND-TREE-successiver将我们左转的最后一个节点的候选节点保留在c中

受谢尔顿解决方案的启发,这是该解决方案的非递归版本


如果candidate==NIL,x是树中的最大值,并且没有后继项。

受Sheldon解决方案启发,这是该解决方案的非递归版本


如果candidate==NIL,x是树中的最大值,并且没有后继项。

我在这里找到了一个不带父指针的顺序后继项的优雅解决方案->

想法是

1.如果节点有右子树,则其后继节点是右子树中的最小元素

如果节点的右子树为空,则其后继者是其祖先之一,可以使用以下算法自上而下找到,而无需父指针: 初始当前节点为root,成功节点=null

案例1:如果搜索元素小于当前_节点,则当前元素是潜在的后续元素-将成功节点放置在当前_节点,并将当前_节点移动到其左节点,因为搜索元素位于左子树中

案例2:如果搜索元素大于当前_节点,则它不是潜在的后续元素。较小的元素如何可以成为后续元素?。因此,无需将成功节点放在此处,只需将当前节点移到右侧


继续重复此过程,直到达到null或元素本身并返回成功节点。

我找到了一个优雅的解决方案,用于在没有父指针的情况下排序后续项->

想法是

1.如果节点有右子树,则其后继节点是右子树中的最小元素

如果节点的右子树为空,则其后继者是其祖先之一,可以使用以下算法自上而下找到,而无需父指针: 初始当前节点为root,成功节点=null

案例1:如果搜索元素小于当前_节点,则当前元素是潜在的后续元素-将成功节点放置在当前_节点,并将当前_节点移动到其左节点,因为搜索元素位于左子树中

案例2:如果搜索元素大于当前_节点,则它不是潜在的后续元素。较小的元素如何可以成为后续元素?。因此,无需将成功节点放在此处,只需将当前节点移到右侧


不断重复该过程,直到达到null或元素本身并返回成功节点。

递归Java解决方案可以如下所示:

public Integer successor(Integer value) {
    Node n = succ(root, value, null);
    if (null != n) {
       return n.value;
    }
    return null;
}

private Node succ(Node n, Integer x, Node p) {
    if (null == n) {
        return null;
    }

    if (x < n.value) {
        return succ(n.left, x, n);
    } else if (x > n.value) {
        return succ(n.right, x, p);
    }
    if (null != n.right) {
        return min(n.right);
    }
    return p;
}
作为一个客户机,我们只需传入我们想要知道其后续节点的值。然后我们开始从根开始搜索,直到找到我们要查找的值。现在有两种情况:

如果当前节点有一个右子节点,则后继节点是当前节点右子树中最小的元素 否则,它就是node p parent指针,只有当我们在树中向左移动时,它才被更新
递归Java解决方案可以如下所示:

public Integer successor(Integer value) {
    Node n = succ(root, value, null);
    if (null != n) {
       return n.value;
    }
    return null;
}

private Node succ(Node n, Integer x, Node p) {
    if (null == n) {
        return null;
    }

    if (x < n.value) {
        return succ(n.left, x, n);
    } else if (x > n.value) {
        return succ(n.right, x, p);
    }
    if (null != n.right) {
        return min(n.right);
    }
    return p;
}
作为一个客户机,我们只需传入我们想要知道其后续节点的值。然后我们开始从根开始搜索,直到找到我们要查找的值。现在有两种情况:

如果当前节点有一个右子节点,则后继节点是当前节点右子树中最小的元素 否则,它就是node p parent指针,只有当我们在树中向左移动时,它才被更新
你的回答很好,我认为是正确的。我试图在这里做类似的事情,也就是从根开始跟踪候选对象,但是我没能像你在这里展示的那样提出一个好的递归形式。谢谢。@Sheldon,最后一个语句应该是if,然后应该是b
e已删除。此算法不正确。首先,它无法通过简单测试:如果x=root,它总是返回null。第二,假设您有一个最左边节点的树,它有一个右兄弟节点和一个左子节点。该算法总是错误地将父节点作为最左侧节点的后续节点返回。您的答案非常好,我认为它是正确的。我试图在这里做类似的事情,也就是从根开始跟踪候选对象,但是我没能像你在这里展示的那样提出一个好的递归形式。谢谢。@Sheldon,最后一个语句应该是if,然后应该删除。这个算法不正确。首先,它无法通过简单测试:如果x=root,它总是返回null。第二,假设您有一个最左边节点的树,它有一个右兄弟节点和一个左子节点。该算法总是错误地将父节点作为最左侧节点的后继节点返回。我们可以假设,找到顺序后继节点的方法具有可用的“根”。我们将使用“根”沿树向下走,而不是从节点“X”沿树向上走,在到达“X”之前,我们将继续标记“可能的”顺序。最后,我们可以返回结果。我们可以假设找到顺序后继者的方法具有可用的“根”。我们将使用“根”沿树向下走,而不是从节点“X”沿树向上走,在到达“X”之前,我们将继续标记“可能的”顺序。最后,我们可以返回结果。作为的副本关闭-虽然该帖子没有在不使用父指针的情况下查找它的限制,但某些答案不使用父指针。作为的副本关闭-而该帖子没有在不使用父指针的情况下查找它的限制,有些答案不使用父指针。