简体   繁体   中英

Binary search tree iterator c#

I have problem with method MoveNext in my enumerator. I need iterator for binary search tree. In construcotr of my enumerator I initialize Node to root of tree. Current is value that I ened to return for next item. This code for method moveNext return wrong values.

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;

    }

I see a few issues with that code. First, in the else -branch, you are changing the value of a node in the tree - You probably meant to write Current = node.Value; instead of node.Value = Current; .

However, that's not the main issue. Your iterator will get stuck in an infinite loop really easily. Everything looks reasonable for traversing down, you take the leftmost path down to a leaf node.

Then you backtrack up until you find an ancestor node which has a Right child and yield the value of that node. However, this value was already returned by the iterator on the way down. Also, you don't remember which path you already traversed down, so on the next step you will inevitably follow the same path down again that you took before, then you'll backtrack up again and so on, ad infinitum.

In order to fix this, don't stop at the parent node when you backtrack - take the first step down the next path already. It is true that this will always be the Right child of some node, but it is not necessarily the Right child of the first ancestor that has one, because you might already be backtracking up from that branch.

So to summarize: If you can't go down any further, backtrack up one level. Check if you are coming from the Left or the Right child node. If you came from the left one, go down the right one if it exists, and set Current to its value. If it doesn't, or if you already come from the right child, recurse upwards another level.

Your enumerator modifies the tree:

Node.Value = Current;

Enumerators shouldn't do that.

In the last else you are changing the value of the node to the same value as the current node:

node.Value = Current;

I think that you tried to put the current node in the node variable, but that's not done by putting the current value in the value of the current node, and it's not needed as the node variable already contains the current node.

As Medo42 pointed out, if you are coming from the Right node, all children of that parent has already been iterated, so you should check for that when looking for a parent to continue iterating:

} while (node.Right == null || node.Right == last);

When you have looped up the parent chain to find the right parent, you are using the parent instead of getting the child:

node = node.Right;

So:

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;

}

I posted my solution here Binary Search Tree Iterator java

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

Here is algorithm how to do so (you can implement it in any language you like then).

ArrayIterator

BSTITerator what uses an array under the hood.

Perform inorder traversal and collect visited nodes into a list. ArrayIterator. Now it works similar to list iterator, which is easy to implement.

next() and hasNext() - have constant time complexity; however, this iterator requires memory for N elements of the tree.

StackIterator

All nodes to be returned in next() call are stored in stack. Each time, you return next node, you remove element from the stack (let's name it currentNode ). If currentNode has a right child (you have already returned left), you put the right child into the stack. Then you need to iterate left subtree of the right child and put all left elements into the stack.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM