对于二叉树对象,我正在使用私有字段来实现
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.left
和endKey.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.left
或endKey.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);
}
}
}