[英]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; }
}
如果你想拥有的每个节点也知道其母公司,这是确定的,但所有的遍历是通过什么堆栈上,并使用添加到堆栈left
和right
子链接。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.