二进制树的有序迭代器

Pau*_* S. 25 java algorithm binary-tree iterator nodes

我如何编写一个Java迭代器(即需要nexthasNext方法),它采用二叉树的根,并按顺序迭代二叉树的节点?

Joh*_*rak 39

子树的第一个元素始终是最左边的元素.元素之后的下一个元素是其右子树的第一个元素.如果元素没有正确的子元素,则下一个元素是元素的第一个右祖先.如果元素既没有右子也没有右祖先,那么它就是最右边的元素,它是迭代中的最后一个元素.

我希望我的代码是人类可读的并涵盖所有情况.

public class TreeIterator {
    private Node next;

    public TreeIterator(Node root) {
        next = root;
        if(next == null)
            return;

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

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

    public Node next(){
        if(!hasNext()) throw new NoSuchElementException();
        Node r = next;

        // If you can walk right, walk right, then fully left.
        // otherwise, walk up until you come from left.
        if(next.right != null) {
            next = next.right;
            while (next.left != null)
                next = next.left;
            return r;
        }

        while(true) {
            if(next.parent == null) {
                next = null;
                return r;
            }
            if(next.parent.left == next) {
                next = next.parent;
               return r;
            }
            next = next.parent;
        }
     }
 }
Run Code Online (Sandbox Code Playgroud)

考虑以下树:

     d
   /   \
  b     f
 / \   / \
a   c e   g
Run Code Online (Sandbox Code Playgroud)
  • 第一个元素是"完全离开根"
  • a 没有合适的孩子,所以下一个元素是"直到你从左边来"
  • b确实有一个正确的孩子,所以迭代b正确的子树
  • c没有合适的孩子.这是父母b,已被遍历.下一个父母是d,没有被遍历,所以停在这里.
  • d有一个正确的子树.它最左边的元素是e.
  • ...
  • g没有正确的子树,所以走吧.f因为我们来自正确的,所以已经参观了.d已被访问过.d没有父母,所以我们不能进一步向上.我们来自最右边的节点,我们已经完成了迭代.

  • @Vic然后你需要一堆各种各样的.由于Java没有生成器/协同程序(除非Java 8引入它们),因此必须使用显式堆栈.只需记住列表中的父母列表,然后在您想要上升时弹出一个. (3认同)
  • 我没有在答案中发布有效的迭代器是有原因的,因此OP必须自己做。给出这样的答案不会使任何人受益。 (2认同)
  • @HunterMcMillen好点。豪勒,这绝对不是复制粘贴的事情。至少必须更改一行;-),但我承认这不是故意的。我的重点是可读性,而不是正确性。我什至没有测试;-) (2认同)
  • 如果没有父指针怎么办? (2认同)
  • 这个答案的一个问题是**每个 TreeNode 都需要存储父节点**,否则我们需要单独存储父节点的路径或使用堆栈来形成迭代器。 (2认同)