我有一个包含这样节点的二叉树:
class Foo (x: Int, y: Int, z: Int) {}
fun main(args: Array<String>) {
val ft1 = ::Foo
val ft2: KFunction3<Int, Int, Int, Foo> = ::Foo
}
由于某种原因,我的插入函数(向树添加元素)在10次迭代后停止工作,这意味着它将元素添加到不正确的节点中(不遵循二叉树模式)。谁知道它为什么会破裂?感谢。
答案 0 :(得分:1)
我认为它实际上是在11次迭代之后,而不是10次。
那是因为在11次迭代之后你的树看起来像这样:
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ / \
8 9 10 11
现在你想要在6下加12,为此你的addItemToTree
,当看1时,需要向右移动。但是,只有正确的孩子没有自己的孩子,它才会走向正确。在这种情况下,1的右边孩子是3,并且它有自己的孩子,所以你的方法将向左移动,这是错误的。
要修复它,您需要维护一些有关节点的辅助信息,以便您决定何时向左和向右移动。一些选择:
存储子树中的节点总数。如果左子树的子女数量少于2,而右孩子的数量少于1,则向右移动(尝试证明为什么有效)。
存储子树是否在当前深度处有开口。如果left->hasOpenings
或!left->hasOpenings && !right->hasOpenings
(后者表示树在当前深度已满,需要延长),则转到左侧子项。每当你递归到节点的左子节点时,就为节点的父节点设置hasOpenings
。
在addItemToTree
中保持当前深度(根的深度为0)。设leftmostOne
为item
二进制表示中最左边1的索引。如果item & (1 << (leftmostOne - depth - 1)) == 0
,请转到左侧。例如。当你添加9时,leftmostOne
是3.然后你将进行三次迭代,并做出以下决定:
9 & (1 << (3 - 0 - 1)) = 0
,左转9 & (1 << (3 - 1 - 1)) = 0
,左转9 & (1 << (3 - 2 - 1)) = 1
,右转这正是你想要的。 试着证明为什么这适用于一般情况。