我的枚举器中的方法MoveNext有问题。我需要二进制搜索树的迭代器。在我的枚举器的construcotr中,我将Node初始化为树的根。 当前是我为下一个项目返回的价值。方法moveNext的此代码返回错误的值。
public bool MoveNext()
{
if (Current == null)
Current = node.Value;
else if (node.Left != null)
{
node = node.Left;
Current = node.Value;
}
else if (node.Right != null)
{
node = node.Right;
Current = node.Value;
}
else
{
node.Value = Current;
do
{
if (node.Parent == null)
return false;
node = node.Parent;
} while (node.Right == null);
Current = node.Value;
}
return true;
}
答案 0 :(得分:2)
我看到该代码存在一些问题。首先,在else
- 分支中,您正在更改树中节点的值 - 您可能想要编写Current = node.Value;
而不是node.Value = Current;
。
但是,这不是主要问题。你的迭代器将很容易陷入无限循环。对于遍历,一切看起来都合理,您将最左边的路径向下移动到叶节点。
然后你回溯直到你发现一个祖先节点有一个Right
子节点并产生该节点的值。但是,迭代器在返回时已返回此值。此外,你不记得你已经走过的路径,所以在下一步你将不可避免地再次按照你之前的路径走下去,然后你将再次回溯,依此类推,无限制。
为了解决这个问题,请不要在回溯时停在父节点上 - 已经迈出了下一个路径的第一步。确实,这将始终是某个节点的Right
子节点,但它不一定是具有一个节点的第一个祖先的Right
子节点,因为您可能已经从那个分支回溯。
总而言之:如果你不能再进一步下去,那就回溯一个层次。检查您是来自Left
还是Right
子节点。如果您来自左侧,请向右移动,如果存在,则将Current
设置为其值。如果没有,或者你已经来自正确的孩子,则向上递增另一个级别。
答案 1 :(得分:1)
您的枚举器修改树:
Node.Value = Current;
调查员不应该这样做。
答案 2 :(得分:0)
在最后的其他情况下,您将节点的值更改为与当前节点相同的值:
node.Value = Current;
我认为你试图将当前节点放在node
变量中,但这不是通过将当前值放在当前节点的值中来完成的,而不是node
所需要的。变量已包含当前节点。
正如Medo42指出的那样,如果你来自Right节点,那个父节点的所有子节点都已经被迭代了,所以在寻找父节点继续迭代时你应该检查它:
} while (node.Right == null || node.Right == last);
当你找到父链以找到正确的父级时,你正在使用父级而不是获取子级:
node = node.Right;
所以:
public bool MoveNext() {
if (Current == null)
Current = node.Value;
else if (node.Left != null)
{
node = node.Left;
Current = node.Value;
}
else if (node.Right != null)
{
node = node.Right;
Current = node.Value;
}
else
{
Node last;
do
{
if (node.Parent == null)
return false;
last = node;
node = node.Parent;
} while (node.Right == null || node.Right == last);
node = node.Right;
Current = node.Value;
}
return true;
}
答案 3 :(得分:0)
我在这里发布了我的解决方案 Binary Search Tree Iterator java
这里是算法的实现方法(您可以用自己喜欢的任何语言来实现)。
BSTITerator在幕后使用什么数组。
执行顺序遍历并将访问的节点收集到列表中。 ArrayIterator。现在,它的工作方式类似于列表迭代器,易于实现。
next()
和hasNext()
-具有恒定的时间复杂度;但是,此迭代器需要存储N个树元素。
在next()
调用中要返回的所有节点都存储在堆栈中。每次返回下一个节点时,都会从堆栈中删除元素(将其命名为currentNode
)。
如果currentNode
有一个正确的孩子(您已经返回了左边),则将正确的孩子放入堆栈中。然后,您需要迭代右子级的左子树并将所有左元素放入堆栈中。