yield in recursion bst - c#

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();
}

Related

How to do foreach query with also checking null case?

Ok this is what i am doing right now but i wonder are there any better approach to do it?
if (vrChildNode.SelectNodes("//href") != null)
foreach (var vrNodes in vrChildNode.SelectNodes("//href"))
{
}
As you can see i am actually querying 2 times. First for null check and second for foreach.
If i do the way below it throws error if there is no nodes
foreach (var vrNodes in vrChildNode.SelectNodes("//href"))
{
}
Thank you for answers
c# .net 4.5
You can create an extension method to do the check and ensure the result is non-null:
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source)
{
return source ?? Enumerable.Empty<T>();
}
Then you can write:
foreach (var vrNodes in vrChildNode.SelectNodes("//href").EmptyIfNull())
{
}
The best and clearest way is to store it in a variable:
var nodes = vrChildNodes.SelectNodes("//href");
if (nodes != null)
foreach (var vrNodes in nodes)
{
}
A less clean and less obvious way, but a single liner:
foreach (var vrNodes in vrChildNodes.SelectNodes("//href") ?? Enumerable.Empty<nodeType>)
{
}
I'd really suggest you to do the first. Everyone will see what you meant with a single look. With the second approach, you really first have to look and think about what the purpose is (I think it is already horrible result that SelectNodes can return null, but I know that's not in your hand).
If you like you can also create an extension method to do a check for you:
public static IEnumerable<nodeType> SelectNodesSafe(this typeOfvrChildNodes t, string selector)
{
var res = t.SelectNodes(selector);
if (res == null)
return Enumerable.Empty<nodeType>();
else // Redundant else
return res;
}
foreach (var vrNodes in vrChildNode.SelectNodes("//href") ?? Enumerable.Empty<type>)
{
}

Check if IEnumerable has ANY rows without enumerating over the entire list

I have the following method which returns an IEnumerable of type T. The implementation of the method is not important, apart from the yield return to lazy load the IEnumerable. This is necessary as the result could have millions of items.
public IEnumerable<T> Parse()
{
foreach(...)
{
yield return parsedObject;
}
}
Problem:
I have the following property which can be used to determine if the IEnumerable will have any items:
public bool HasItems
{
get
{
return Parse().Take(1).SingleOrDefault() != null;
}
}
Is there perhaps a better way to do this?
IEnumerable.Any() will return true if there are any elements in the sequence and false if there are no elements in the sequence. This method will not iterate the entire sequence (only maximum one element) since it will return true if it makes it past the first element and false if it does not.
Similar to Howto: Count the items from a IEnumerable<T> without iterating? an Enumerable is meant to be a lazy, read-forward "list", and like quantum mechanics the act of investigating it alters its state.
See confirmation: https://dotnetfiddle.net/GPMVXH
var sideeffect = 0;
var enumerable = Enumerable.Range(1, 10).Select(i => {
// show how many times it happens
sideeffect++;
return i;
});
// will 'enumerate' one item!
if(enumerable.Any()) Console.WriteLine("There are items in the list; sideeffect={0}", sideeffect);
enumerable.Any() is the cleanest way to check if there are any items in the list. You could try casting to something not lazy, like if(null != (list = enumerable as ICollection<T>) && list.Any()) return true.
Or, your scenario may permit using an Enumerator and making a preliminary check before enumerating:
var e = enumerable.GetEnumerator();
// check first
if(!e.MoveNext()) return;
// do some stuff, then enumerate the list
do {
actOn(e.Current); // do stuff with the current item
} while(e.MoveNext()); // stop when we don't have anything else
The best way to answer this question, and to clear all doubts, is to see what the 'Any' function does.
public static bool Any<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) return true;
}
return false;
}
https://github.com/microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs

Recursive Iterators

I am having some trouble making an iterator that can traverse the following type of data structure.
I have a class called Expression, which has one data member, a List<object>.
This list can have any number of children, and some of those children might be other Expression objects.
I want to traverse this structure, and print out every non-list object (but I do want to print out the elements of the list of course), but before entering a list, I want to return "begin nest" and after I just exited a list, I want to return "end nest".
I was able to do this if I ignored the class wherever possible, and just had List<object> objects with List<object> items if I wanted a subExpression, but I would rather do away with this, and instead have an Expressions as the sublists (it would make it easier to do operations on the object. I am aware that I could use extension methods on the List<object> but it would not be appropriate (who wants an Evaluate method on their list that takes no arguments?).
The code that I used to generate the origonal iterator (that works) is:
public IEnumerator GetEnumerator(){
return theIterator(expr).GetEnumerator();
}
private IEnumerable theIterator(object root) {
if ((root is List<object>)){
yield return " begin nest ";
foreach (var item in (List<object>)root){
foreach (var item2 in theIterator(item)){
yield return item2;
}
}
yield return " end nest ";
}
else
yield return root;
}
A type swap of List<object> for expression did not work, and lead to a stackOverflow error. How should the iterator be implemented?
Update: Here is the swapped code:
public IEnumerator GetEnumerator() {
return this.GetEnumerator();
}
private IEnumerable theIterator(object root) {
if ((root is Expression)) {
yield return " begin nest ";
foreach (var item in (Expression)root) {
foreach (var item2 in theIterator(item))
yield return item2;
}
yield return " end nest ";
}
else
yield return root;
}
The reason you are getting a StackOverflowException is that
foreach (var item in (Expression)root)
…internally causes:
((Expression)root).GetEnumerator()
…to be invoked – that is the way that the CLR enumerates the objects that must be assigned to the item variable during each iteration of the foreach loop.
In your case, the GetEnumerator() invocation would cause theIterator to be executed again for the same root, thereby entering an infinite recursion.
To fix your problem, you need to replace:
foreach (var item in (Expression)root)
…with:
foreach (var item in ((Expression)root).expr)
…where expr is the name of the List<object> property.
Why did you change GetEnumerator() to return this.GetEnumerator()?
It seems to me that's where your stack overflow is coming from.
Try making it return theIterator(this).GetEnumerator()?

Question on binary search tree

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.

Handling common recursive functions

I've noticed that in my project, we frequently are writing recursive functions.
My question is: is there any way to create the recursive function as generic function for each hierarchy structure that is using the recursive iteration?
Maybe I can use a delegate that gets the root and the end flag of the recursion?
Any ideas?
Thanks.
My question is: is there any way to create the recursive function as generic function for each hierarchy structure that is using the recusive iteration?
may be i can use a delegate that gets the root and the end flag of the recursive?
Yes - The only thing you need is a delegate function that computes a list of children for each element. The function terminates when no children are returned.
delegate IEnumerable<TNode> ChildSelector<TNode>(TNode Root);
static IEnumerable<TNode> Traverse<TNode>(this TNode Root, ChildSelector<TNode> Children) {
// Visit current node (PreOrder)
yield return Root;
// Visit children
foreach (var Child in Children(Root))
foreach (var el in Traverse(Child, Children))
yield return el;
}
Example:
static void Main(string[] args) {
var Init = // Some path
var Data = Init.Traverse(Dir => Directory.GetDirectories(Dir, "*", SearchOption.TopDirectoryOnly));
foreach (var Dir in Data)
Console.WriteLine(Dir);
Console.ReadKey();
}
I think what you want is a way to work with hierarchical structures in a generic way ("generic" as defined in English, not necessarily as defined in .Net). For example, this is something I wrote once when I needed to get all the Controls inside a Windows Form:
public static IEnumerable<T> SelectManyRecursive<T>(this IEnumerable<T> items, Func<T, IEnumerable<T>> selector)
{
if (items == null)
throw new ArgumentNullException("items");
if (selector == null)
throw new ArgumentNullException("selector");
return SelectManyRecursiveInternal(items, selector);
}
private static IEnumerable<T> SelectManyRecursiveInternal<T>(this IEnumerable<T> items, Func<T, IEnumerable<T>> selector)
{
foreach (T item in items)
{
yield return item;
IEnumerable<T> subitems = selector(item);
if (subitems != null)
{
foreach (T subitem in subitems.SelectManyRecursive(selector))
yield return subitem;
}
}
}
// sample use, get Text from some TextBoxes in the form
var strings = form.Controls
.SelectManyRecursive(c => c.Controls) // all controls
.OfType<TextBox>() // filter by type
.Where(c => c.Text.StartWith("P")) // filter by text
.Select(c => c.Text);
Another example: a Category class where each Category could have ChildCategories (same way a Control has a Controls collection) and assuming that rootCategory is directly or indirectly the parent of all categories:
// get all categories that are enabled
var categories = from c in rootCategory.SelectManyRecursive(c => c.ChildCategories)
where c.Enabled
select c;
I'm not sure what exactly your question is asking for but a recursive function can be generic. There's no limitation on that. For instance:
int CountLinkedListNodes<T>(MyLinkedList<T> input) {
if (input == null) return 0;
return 1 + CountLinkedListNodes<T>(input.Next);
}
An easier and also generic approach might be to cache the results of the function and use the "real" function only when the result is known - the effectivness of this approach depends how frequently the same set of parameters is used during your recursion.
If you know Perl you should check the first 4 chapters of Higher-Order Perl which are available as a EBook, the ideas presented are language-independent.
It sounds like your solution can successfully use the Visitor Pattern.
You can create a specific variation of the Visitor Pattern by creating a hierarchical visitor pattern.
It is a little complex to discuss entirely here, but that should get you started into some research. The basic idea is that you have a class that knows how to traverse the structure, and then you have Visitor classes that know how to process a particular node. You can separate the traversal of the tree with the processing of nodes.

Categories

Resources