对于我正在使用私有字段实现的二叉树对象
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
结尾的树(可能看起来像LinkedList),而没有包括endKey.left
和{ {1}}。我认为我应该首先从根的左树或右树上递归调用该方法,具体取决于startKey是大于还是小于根密钥,所以:
endKey.right
这将继续在树中导航,直到它到达包含键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
保留为新树的根。
换句话说,我认为我已经设法获得了一个树的子集,该子集从较低级别开始并一直延伸到原始树的底部。如何递归地消除不需要的底部的子代并返回新的子集?
答案 0 :(得分:0)
如果将其视为视图,则实际上并未将其剪切掉,而只是将方法限制为子集的范围。使用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);
}
}
}