对于二叉树对象,我正在使用私有字段来实现

X key;
Y value;
Tree<X,Y> left;
Tree<X,Y> right;


我有一个方法public Tree<X,Y> subset(X startKey, X endKey),该方法需要返回一棵Tree,该树包括startKey节点和endKey节点之间的所有键及其对应的值。还需要使用递归来执行此方法。

我遇到的问题是我不知道一种获取以endKey结尾但不包括endKey.leftendKey.right的树(可能看起来像LinkedList)的方法。我认为我应该首先从根的左或右树上递归调用该方法,具体取决于startKey是大于还是小于根键,因此:

if (this.key.compareTo(startKey) < 0) this.right.subset(startKey, endKey);
else if (this.key.compareTo(startKey > 0) this.right.subset(startKey, endKey);


这将继续在树中导航,直到它到达包含键startKey的节点上为止。到此为止,我将this复制到新树中,这样就可以避免编辑原始树。这个新树的节点以startKey为根,然后具有与原始树相同的子节点。

这就是我卡住的地方。我知道我必须处理的问题是导航到endKey,确保我停在那里并且不包含endKey.leftendKey.right,并且即使方法从“展开”时也正确返回了子集。递归调用。我在想,如果我想在endKey处停止,则必须以某种方式保留对其父节点的引用,以便可以将父节点的左或右子节点设置为键/值对,以便切断endKey的其余孩子。但是,由于我实际上没有节点对象,并且无法添加任何方法或构造函数,因此我不知道如何维护对父树的引用。我还不知道如何在保持startKey作为新树的根的同时尝试实现这一目标。

换句话说,我认为我已经设法获得了一个树的子集,该子集从较低级别开始并一直延伸到原始树的底部。如何递归地消除不需要的底部的子代并返回新的子集?

最佳答案

如果将其视为视图,则实际上并没有将其剪切掉,而只是将方法限制为子集的范围。使用iterator()时子图只是具有自己的Iterator实现,该实现从子图的下限开始,并且在达到上限时仅返回hasNext() == false。用户不会注意到他实际上是在原始树上进行迭代,因为它完全被隐藏了。我希望这个例子能让您对此有所了解。

public interface Tree<X, Y> extends Iterable<Tree<X, Y>> {
    X getKey();
    X getValue();
    Tree<X, Y> floor(X key);
    Tree<X, Y> ceiling(X key);
    Tree<X, Y> subTree(X lo, X hi);
    // ...
}

public class TreeImpl<X, Y> implements Tree<X, Y> {
    final X key;
    Y value;
    TreeImpl<X, Y> left, right;

    public TreeImpl(X key, Y value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public Iterator<Tree<X, Y>> iterator() {
        return new TreeItr();
    }

    // Iterator starting at the most left to the most right;
    private class TreeItr implements Iterator<Tree<X, Y>> {
        // ...
    }

    @Override
    public Tree<X, Y> subTree(X lo, X hi) {
        return new SubTree<>(this, lo, hi);
    }

    private static class SubTree<X, Y> implements Tree<X, Y> {
        final Tree<X, Y> backing;
        final X lo, hi;

        public SubTree(Tree<X, Y> backing, X lo, X hi) {
            this.backing = backing;
            this.lo = lo;
            this.hi = hi;
        }

        @Override
        public Iterator<Tree<X, Y>> iterator() {
            return new SubTreeItr(backing.ceiling(lo), backing.floor(hi))
        }

        // Iterator starting at 'from' and returning 'hasNext() == false' after 'to'
        // has returned
        private class SubTreeItr implements Iterator<Tree<X, Y>> {
            final Tree<X, Y> from, to;

            public SubTreeItr(Tree<X, Y> from, Tree<X, Y> to) {
                this.from = from;
                this.to = to;
            }

            //...
        }

        @Override
        public Tree<X, Y> subTree(X lo, X hi) {
            // Check if lo > this.lo && hi < this.hi
            return new SubTree<>(backing, lo, hi);
        }
    }
}

08-07 06:26