[英]Binary search tree iterator c#
我的枚举器中的 MoveNext 方法有问题。 我需要二叉搜索树的迭代器。 在我的枚举器的构造中,我将 Node 初始化为树的根。 Current 是我为下一个项目返回的值。 方法 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;
}
我看到该代码存在一些问题。 首先,在else
分支中,您正在更改树中节点的值 - 您可能打算编写Current = node.Value;
而不是node.Value = Current;
.
然而,这不是主要问题。 你的迭代器很容易陷入无限循环。 向下遍历的一切看起来都是合理的,您可以沿着最左边的路径向下到达叶节点。
然后回溯直到找到一个具有Right
子节点的祖先节点并产生该节点的值。 然而,这个值已经在向下的过程中被迭代器返回了。 此外,你不记得你已经走过了哪条路,所以在下一步你将不可避免地再次沿着你之前走的路向下走,然后你会再次原路返回,如此循环往复。
为了解决这个问题,当你回溯时不要停在父节点上——已经迈出了下一条路径的第一步。 确实,这将始终是某个节点的Right
孩子,但不一定是第一个祖先的Right
孩子,因为您可能已经从该分支回溯。
所以总结一下:如果你不能再往下走,就回溯上一层。 检查您是来自Left
子节点还是Right
子节点。 如果您来自左侧,则从右侧向下移动(如果存在),并将Current
设置为其值。 如果不是,或者如果您已经来自正确的孩子,则向上递归另一个级别。
您的枚举器修改树:
Node.Value = Current;
枚举器不应该这样做。
在最后一个 else 中,您将节点的值更改为与当前节点相同的值:
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;
}
我在这里发布了我的解决方案Binary Search Tree Iterator java
这是如何执行此操作的算法(您可以用您喜欢的任何语言实现它)。
BSTITerator 什么在引擎盖下使用数组。
执行中序遍历并将访问过的节点收集到列表中。 数组迭代器。 现在它的工作方式类似于列表迭代器,很容易实现。
next()
和hasNext()
- 具有恒定的时间复杂度; 然而,这个迭代器需要树的 N 个元素的内存。
在next()
调用中要返回的所有节点都存储在堆栈中。 每次返回下一个节点时,都会从堆栈中删除元素(让我们将其命名为currentNode
)。 如果currentNode
有一个右孩子(您已经返回左),您将右孩子放入堆栈。 然后你需要迭代右孩子的左子树并将所有左元素放入堆栈。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.