I am looking at the following code: http://netrsc.blogspot.com/2010/04/net-c-binary-tree.html
Am I right in thinking that the while (!Found) condition will iterate the tree?
protected void Insert(T item)
{
TreeNode<T> TempNode = Root;
bool Found=false;
while (!Found)
{
int ComparedValue = TempNode.Value.CompareTo(item);
if(ComparedValue<0)
{
if(TempNode.Left==null)
{
TempNode.Left=new TreeNode<T>(item,TempNode);
++NumberOfNodes;
return;
}
else
{
TempNode=TempNode.Left;
}
}
else if(ComparedValue>0)
{
if(TempNode.Right==null)
{
TempNode.Right=new TreeNode<T>(item,TempNode);
++NumberOfNodes;
return;
}
else
{
TempNode=TempNode.Right;
}
}
else
{
TempNode=TempNode.Right;
}
}
}
Also, for the find and traversal methods, how do these work? If nothing is returned from the Traversal method but from the left branch, would the loop in Find execute again? How would it know to execute down the right branch?
protected IEnumerable<TreeNode<T>> Traversal(TreeNode<T> Node)
{
if (Node.Left != null)
{
foreach (TreeNode<T> LeftNode in Traversal(Node.Left))
yield return LeftNode;
}
yield return Node;
if (Node.Right != null)
{
foreach (TreeNode<T> RightNode in Traversal(Node.Right))
yield return RightNode;
}
}
Thanks
An example of iterating the tree is in the Find command, which calls the Traversal function.
foreach (TreeNode<T> Item in Traversal(Root))
The Traversal function will iteratively return the items in the tree in a depth-first, left-to-right manner. If you look at the Traversal code, it calls itself recursively on the left side and then recursively on the right.
Traversal returns the entire tree in an iterable object, where the items are ordered depth-first, left-to-right. The Find command simply loops through each one and when it hits a match returns it breaking out of the loop. Basically, Traversal returns an ordered iterable of items, Find goes through that list looking for a match. Find really doesn't even have to know whether it's searching through a list or a tree or whatever. It just needs something to iterate through to find a match.
Not necessarily. It will only iterate through the nodes on the path of where the inserted node should be added. There are some return statements sprinkled in that loop so it will essentially stop when it find's the correct location and adds the new node. It would have been more appropriate (in the code) to set the Found variable to true instead.
The traversal methods return the nodes of both the left and right subtrees. You should note that it uses yield return and not the plain return. Using it creates an enumerator where each item that is yielded is what the numerator would return as you iterate through it. Think of it as pausing execution when it reaches a yield return statement. When iterating to the next value from the calling code, execution is continued at that point potentially returning more values.
Find will take the results of the traversal and returns the stored value if found in one of the nodes.
Related
I am trying to make an enumerator that iterates over a sublist within a linked list. To do this, I'm explicitly keeping track of the two nodes Head and Tail that bound the sublist. My goal is to be able to call a foreach loop over the linked list, to iterate over all the elements of the sublist.
What foreach wants to do:
The foreach loop first initializes an enumerator, in my case with the required list list and a variable linked list node node from which it will ask the Value during the loop.
Once the loop has been initialized, it repeats the following pattern:
Call the MoveNext() method, which 'increments' the list
Retrieve Current and return it to wherever it's called
Repeat until MoveNext() == false.
How I've currently written my enumerator
Since the first step is to move, rather than to return a value, I figured I could initialize my enumerator like this:
this.list = list;
this.node = list.Head.Previous // Initialize node to be the element before Head
Where Head is the first element of the sublist to be shown.
Then, I tried to implement the logic for MoveNext() and Current like this:
public T Current => node.Value;
object IEnumerator.Current => Current;
public bool MoveNext()
{
node = node.Next;
return node != list.Tail.Next;
}
Where Tail is the last element of the sublist to be shown.
But in some cases, because this implementation of a linked list is circular, list.Tail.Next can be list.Head, meaning that MoveNext() will return false without even getting the chance to return a single value.
Is there a way to refactor the enumerator to make sure it iterates over the entire sublist instead of just short-circuiting, both when list.Tail.Next does and doesn't point to list.Head?
From your description, there seems to be no cases where the first call to MoveNext would return false.
You could just add an extra piece of state called Moved:
private bool Moved { get; set; } = false;
public bool MoveNext()
{
node = node.Next;
var retVal = !Moved || node != list.Tail.Next;
Moved = true;
return retVal;
}
An extra state is definitely needed here, because if you only have one element, we have no way to tell whether we have iterated over it or not, as node = node.Next does not change the state of the enumerator.
Did you try:
public bool MoveNext()
{
bool returnValue = node != list.Tail;
node = node.Next;
return returnValue;
}
I've created a templated bst class and I've implemented GetEnumerator but I'm really not happy with what've done.
so first of all I felt i needed an helper function inner visit
private IEnumerable<Node<T>> innerVisit(Node<T> root)
{
if(root== null)
yield break;
if (root.Left != null)
{
var l = innerVisit(root.Left);
foreach (var item in l)
yield return item;
}
yield return root;
if (root.Right != null)
{
var r = innerVisit(root.Right);
foreach (var item in r)
yield return item;
}
}
I really dislike the repeating code but couldn't find a proper solution to it
, clearly repeating the loop is unclean but also I feel that burying it under a function that would jump into this one would be bad practice to say the least. any suggestion on how to do this properly?
also to complete the implementation I've written
public IEnumerator<Node<T>> GetEnumerator()
{
var res = innerVisit(_root);
foreach (var item in res)
yield return item;
}
but that too feels bad and more of a hack to make sure it will work within foreach loop and etc.
I don't think you can solve your problem without repeating the same operations like you did, but I do think you can do it in a clearer way, it is part of the requirements to return an IEumerable and If you want to do it in a recursive way you can't prevent reapiting the yield operations (but you don't have to write all of them by yourself, System.LINQ will help us with that).
We can replace the foreach and the yield return with Enumerable.Concat method, using it we can concat the left InnerVisit IEnumerable, IEnumerable that we will create for the node itself (an array with 1 item of the current node) and the right InnerVisit IEnumerable:
private IEnumerable<Node<T>> InnerVisit(Node<T> node)
{
if(node == null)
{
return Enumerable.Empty<Node<T>>;
}
return InnerVisit(node.Left).Concat(new[] { node }).Concat(InnerVisit(node.Right));
}
Notice that there is no need to check if Left or Right is null before you call the recursive method because it will check it later in the inner call, if it is null we will return an Enumerable.Empty<Node<T>> instead of using yield break as you did.
We can also simplify GetEnumerator by calling GetEnumerator directly on the result of the root InnerVisit, something like this:
public IEnumerator<Node<T>> GetEnumerator()
{
return InnerVisit(_root).GetEnumerator();
}
I have the recursive function below that is supposed to travel down the tree and display only the root nodes. There are 2 problems with this.
1. Not all code paths return a value.
2. The DisplayLeafNode function will not be called more than once within the for loop since it is returned after the first call.
#functions
{
public static HelperResult DisplayLeafNode(Node node)
{
if (node.nodes != null)
{
for (int i = 0; i < node.nodes.Count; i++)
{
return #DisplayLeafNode(node.nodes[i]);
}
}
else
{
return DisplayNode(node);
}
}
}
#helper DisplayNode(Node node)`enter code here`
{
<a>
#node.NodeName
</a>
}
Can someone help in correcting this?
A recursive function calls itself, so your code should be:
#helper DisplayNode(Node node)
{
<a>
#node.NodeName
</a>
#if(node.Nodes != null)
#foreach(Node innernode in node.Nodes)
{
#DisplayNode(innernode)
}
}
And just call #DisplayNode(root) in your template (meaning the DisplayLeafNode function is not necessary).
Specifically what are you trying to achieve? What do you want to return? Lets say you want to return Node. I believe a Node would have 2 props (a value and and an other reference to its Node. or may be a list of node).
To reply on what to achieve it would be more useful to know how you have arranged your data structure for Node.
Based on your ds you can device a cleaner algorithmic approach to check for a node ref and based on its count, to go further down or further up to reach your last node or parent node.
If you have to return a HelperResult and not find a suitable way to do it, then you could better create a new HelperResult. A sure flaw if you are picky about memory consumption,
but would rather device a cleaner approach on when you want to return and what you want to return.
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.
I need to iterate through a LinkedList<T> (in .NET 2.0) and remove all the items according to a given criteria.
It was easy way under Java, since I could do the following:
Iterator<E> i = list.iterator();
while (i.hasNext()) {
E e = i.next();
if (e == x) {
// Found, so move it to the front,
i.remove();
list.addFirst(x);
// Return it
return x;
}
}
Unfortunately, in the .NET behavior of IEnumerator<T> (the equivalent of Iterator<E>) there's no remove method to remove the current element from the collection.
Also, in the LinkedList<T> there's no way to access an element at a given index, to accomplish the task by iterating back from the last to the first.
Have you got any idea on how to do it? Thank you very much!
This will remove all nodes that match a criteria, in one loop through the linked list.
LinkedListNode<E> node = list.First;
while (node != null)
{
var next = node.Next;
if (node.Value == x) {
list.Remove(e);
}
node = next;
}
I believe that's what you're attempting... You also added back in the node at the beginning of the list (so your java code didn't remove all of the nodes, but rather moved the first matching to the beginning of the list). That would be easy to do with this approach, as well.
It's actually a lot easier in C#.
function PlaceAtHead(<T> x)
{
list.Remove(x);
list.AddFirst(x);
return x;
}
One ugly option is to iterate through your list, find all the items that apply and store them in a list. Then iterate through your second list and call remove on your LinkedList...
I'm hoping someone else has a more elegant solution :)
Just a little addition to Reed Copsey's answer with a predicate:
public static T MoveAheadAndReturn<T>(LinkedList<T> ll, Predicate<T> pred)
{
if (ll == null)
throw new ArgumentNullException("ll");
if (pred == null)
throw new ArgumentNullException("pred");
LinkedListNode<T> node = ll.First;
T value = default(T);
while (node != null)
{
value = node.Value;
if (pred(value))
{
ll.Remove(node);
ll.AddFirst(node);
break;
}
node = node.Next;
}
return value;
}