二叉搜索树迭代器c#

时间:2013-10-27 10:50:25

标签: c# tree iterator

我的枚举器中的方法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;

    }

4 个答案:

答案 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

源代码 https://github.com/yan-khonski-it/bst/blob/master/bst-core/src/main/java/com/yk/training/bst/iterators/BSTIterator.java

这里是算法的实现方法(您可以用自己喜欢的任何语言来实现)。

ArrayIterator

BSTITerator在幕后使用什么数组。

执行顺序遍历并将访问的节点收集到列表中。 ArrayIterator。现在,它的工作方式类似于列表迭代器,易于实现。

next()hasNext()-具有恒定的时间复杂度;但是,此迭代器需要存储N个树元素。

StackIterator

next()调用中要返回的所有节点都存储在堆栈中。每次返回下一个节点时,都会从堆栈中删除元素(将其命名为currentNode)。 如果currentNode有一个正确的孩子(您已经返回了左边),则将正确的孩子放入堆栈中。然后,您需要迭代右子级的左子树并将所有左元素放入堆栈中。