【问题标题】:Binary Search tree inorder iterator next method二叉搜索树中序迭代器下一个方法
【发布时间】:2020-12-07 17:58:41
【问题描述】:

我正在构建一个二叉搜索树类,它有一个中序迭代器和一个预序迭代器。我已经为中序迭代器编写了一个尝试,但我认为我的代码不正确。我阅读了一些关于对迭代器进行编码的指南,并采用了我所解释的内容并尝试在我的设计中实现它。返回树的 hasNext 是有问题的。目前 tree.isEmpty() 返回树的根节点是否为空。我不确定在树的迭代期间检查是否正确。

我对我对 Inorder 迭代如何工作的理解并不完全有信心。目前,我从 root.left 开始使用 next() 方法,而不是尝试从那里进行迭代。

代码澄清的一些注意事项 E = 节点的元素/数据 K = 键

public class BSTIterator<E, K> implements StructureIterator<E> {

    private final BST<E, K> tree;
    BSTNode<E> root =null;
//    Comparator<E> sortFct;
//    BiFunction<K, E, Integer> searchFct;

    public BSTIterator( BSTNode<E> root,Comparator<E> sortFct,
                        BiFunction<K, E, Integer> searchFct) {
        this.tree = new BST<E, K>(sortFct, searchFct);
        this.root = root;
    }

    @Override
    public E next() {
        BSTNode<E> node = tree.root.getLeft();
        E result = node.getData();
        if(node.getRight() != null){
            while(node != null){
                tree.root.getRight();
                node = node.getLeft();
            }
        }
        return result;
    }

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

【问题讨论】:

    标签: java iterator binary-search-tree inorder


    【解决方案1】:

    首先,检查构造函数。 Iterators 应该很快并且通常使用底层数据结构的live copy。因此,我建议不要每次都创建新树。

    public BSTIterator(BST<E, K> tree) {
        this.currentNode = tree.getRoot();
    }
    

    现在,要在不使用递归的情况下遍历树结构,您可以使用Stack。另外,跟踪当前访问的节点。

    Stack<BSTNode<E>> stack = new Stack<>();
    BSTNode<E> currentNode;
    

    现在,next() 方法。首先,如果当前迭代器没有更多元素,请确保抛出NoSuchElementException。我们现在只使用!hasNext()。 然后按照以下步骤操作:

    • 将节点推入堆栈,直到当前节点没有左子节点。
    • 如果currentNodenullStack不为空,则pop()为节点,将currentNode更新为右子节点并返回包含的节点数据。下次调用next()时,会在这个位置继续遍历。
    • 如果currentNodenull 并且堆栈为空,则说明您已完成。

    这是next()的实现:

    @Override
    public E next() {
        if(!hasNext())
            throw new NoSuchElementException();
    
        while(!stack.empty() || currentNode != null) {
            if(currentNode != null) {
                stack.push(currentNode);
                currentNode = currentNode.getLeft();
            } else {
                BSTNode<E> node = stack.pop();
                currentNode = node.getRight();
            
                return node.getData();
            }
        }
    }
    

    从这里开始,只剩下hasNext()。这个方法现在也应该很清楚了,因为它可以通过反转next()中的while条件来实现。

    @Override
    public boolean hasNext() {
        return stack.empty() && currentNode == null;
    }
    

    高级功能:

    大多数 Java 集合都会跟踪修改计数或简称 modCount。它存储一个集合被修改的次数。此数据可用于检测底层数据结构何时在迭代时被非法修改。只需将modCount 传递给Iterator。当然,您必须在树中实现该功能,并在每次修改时递增数字。

    public BSTIterator(BST<E, K> tree) {
        this.tree = tree;
        this.currentNode = tree.getRoot();
        this.expectedModCount = tree.modCount;
    }
    

    然后,实现快速失败的行为:

    @Override
    public E next() {
        if(expectedModCount != tree.modCount)
            throw new ConcurrentModificationException();
        // ...
    }
    

    【讨论】:

    • 谢谢你这很有道理,谢谢你的详细回复。
    猜你喜欢
    • 1970-01-01
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 2020-12-12
    相关资源
    最近更新 更多