繁体   English   中英

如何在二叉树中找到下一个顺序继承者?

[英]How to find the next in order successor in a binary tree?

我正在尝试在我自己的TreeSet类中实现Iterator。 但是,我创建它的尝试仅适用于当前节点是根节点。 迭代器看起来像这样:

构造函数:

public TreeWordSetIterator()
{
    next = root;

    if(next == null)
        return;

    while(next.left != null)
        next = next.left;
}

hasNext:

public boolean hasNext()
{
    return next != null;
}

下一个:

public TreeNode next()
{
    if(!hasNext()) throw new NoSuchElementException();

    TreeNode current = next;

    next = findNext(next); // find next node

    return current;
}

找下一个:

private TreeNode findNext(TreeNode node)
{
    if(node.right != null)
    {
        node = node.right;

        while(node.left != null)
            node = node.left;

        return node;
    }
    else
    {
        if(node.parent == null)
            return null;

        while(node.parent != null && node.parent.left != node)
            node = node.parent;

        return node;
    }
}

这工作正常,直到我到达我的根节点。 所以我只能遍历root的左子,而不是右。 谁能给我一些关于我做错的提示? 我不指望一个解决方案,只是一些提示。

问题:如果每个节点指向其父节点,左子节点和右子节点,如何在TreeSet中找到下一个节点。

提前致谢

您可以通过3种主要方式迭代二进制树

private void inOrder(TreeNode node) {
    if(isEmpty())return;
    if(node.getLeftNode()!=null)inOrder(node.getLeftNode());
    System.out.print(node.getNodeData()+" ");
    if(node.getRightNode()!=null)inOrder(node.getRightNode());
}

private void preOrder(TreeNode node) {
    if(isEmpty())return;
    System.out.print(node.getNodeData()+" ");
    if(node.getLeftNode()!=null)preOrder(node.getLeftNode());
    if(node.getRightNode()!=null)preOrder(node.getRightNode());
}

private void postOrder(TreeNode node) {
    if(isEmpty())return;
    if(node.getLeftNode()!=null)postOrder(node.getLeftNode());
    if(node.getRightNode()!=null)postOrder(node.getRightNode());
    System.out.print(node.getNodeData()+" ");
}

//use
inOrder(root);
preOrder(root);
postOrder(root);

它很简单,你的代码对我来说真的没有意义,除了以这种方式之一进行迭代之外,还有其他的东西吗?

它有助于考虑二叉搜索树的规则。 假设先前返回的节点是n

  • 如果n具有右子树,则具有下一个值的节点将是右子树的最左侧节点。
  • 如果n没有正确的子树,则具有下一个值的节点将是n的第一个祖先,其左侧子树中包含n

您的代码正确处理第一种情况,但不是第二种情况。 考虑node是树的最左边的叶子(起始情况)的情况。 node没有正确的孩子,所以我们直接去else node有父node ,因此跳过if子句。 node.parent.left == node ,因此跳过while子句而不执行任何操作。 最终结果是返回node 我希望你的迭代器继续永远返回同一个节点。

我认为你需要在你的迭代器中保存前一点,这样你才能知道你以前的位置

这里有一些代码,但要注意它不完整,你应该自己做,这只是为了向你展示这个想法。 它也不处理根节点。

findNext(TreeNode node, TreeNode previousNode) {

  if(node.left != null && node.left != previousNode && node.right != previousNode){ //go left if not been there yet
    return node.left; 
  }
  if(node.right != null && node.right != previousNode){ //go right if not been there yet
    return node.right;
  }
  return findNext(node.parent, node); //go up and pass current node to avoid going down
}

一个好的方法是使用堆栈来管理排序,如果你使用递归遍历(而不是试图建立一个Iterator),这就像你在SteveL的回答中所描述的那样。

当你想从左边开始时,你首先按照正确的顺序将根节点及其最左边的子节点加载到堆栈中(从根部向左下方推送)。

始终从堆栈顶部弹出下一个,然后推送其右子(如果有的话)及其最左边的子项,然后返回刚刚弹出的子项,以便它们排在下一行。

通过这种方法,堆栈的顶部将始终是返回的下一个,当堆栈为空时,不再有...

在代码中:

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Stack;

public class TreeNodeInOrderIterator<T> implements Iterator<T> {

    private final Stack<TreeNode<T>> stack;

    public TreeNodeInOrderIterator(TreeNode<T> root) {
        this.stack = new Stack<TreeNode<T>>();
        pushLeftChildren(root);
    }

    @Override
    public boolean hasNext() {
        return !stack.isEmpty();
    }

    @Override
    public T next() {
        if (!hasNext())
            throw new NoSuchElementException();
        TreeNode<T> top = stack.pop();
        pushLeftChildren(top.right);
        return top.val;
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }

    private void pushLeftChildren(TreeNode<T> cur) {
        while (cur != null) {
            stack.push(cur);
            cur = cur.left;
        }
    }

}

在此代码中, TreeNode由。定义

public class TreeNode<T> {
    T val;
    TreeNode<T> left;
    TreeNode<T> right;
    TreeNode(T x) { val = x; }
}

如果你想拥有的每个节点也知道其母公司,这是确定的,但所有的遍历是通过什么堆栈上,并使用添加到堆栈leftright子链接。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM