【发布时间】:2018-11-19 13:02:53
【问题描述】:
对于我使用私有字段实现的二叉树对象
X key;
Y value;
Tree<X,Y> left;
Tree<X,Y> right;
我有一个方法public Tree<X,Y> subset(X startKey, X endKey),它需要返回一个树,包括在startKey 的节点和endKey 的节点之间的所有键,以及它们对应的值。这个方法也需要使用递归来执行。
我遇到的问题是我无法找到一种方法来获取以endKey 结尾的树(可能看起来像一个LinkedList),而不包括endKey.left 和endKey.right。我想我应该首先在根的左树或右树上递归调用该方法,具体取决于 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 保持为新树的根的同时尝试完成此操作。
换句话说,我想我已经设法获得了一个从较低级别开始并继续到原始树底部的树的子集。如何递归地消除我不想要的底部的孩子并返回我的新子集?
【问题讨论】:
-
如果您的子集可以是视图,这意味着对它的更新会影响原始树,反之亦然,您可以使用原始树作为子集中的后备树。子集中的方法只是检查您是否在子集的“范围内”,但您在原始树上执行这些方法。你可以得到子集的一个子集,这意味着它是递归的。这正是
TreeMap及其可导航子视图的工作原理。 -
正如 Meini 所说,您可以像 List.sublist() 那样将其视为 视图,或者您可以制作子树的 副本。作业需要哪种实现。另外请发布更多代码,也许是MCVE。
-
@xtratic 我不确定我是否想将其视为一个视图,这样做是否意味着我在返回其子集的过程中更改了原始树?我很确定制作子树的副本是我想要的。
-
关于@Meini 所说的,我认为 TreeMap 的 subMap() 方法正是我想要的,但我不明白如何“结束”我剪切的子图在它获得一个具有特定键的孩子后关闭它。
标签: java recursion tree binary-tree binary-search-tree