BInary Search Tree iterator c# without parent property - c#

I recently started making a Binary Search Tree in C# in order to practice. After completing this task I decided to implement ICollection<T> so that my tree can be used with a foreachand just in general in order for me to practice.
I've constructed my classes in such a way that I have a Node<T> class and a BinarySearchTree<T> class that contains a Node<T> a Count integer and a IsReadOnly boolean. This is my Node Class:
internal class Node<T>: INode<T> where T: IComparable<T>
{
public Node<T> RightChildNode { get; set; }
public Node<T> LeftChildNode { get; set; }
public T Key { get; set; }
//some methods go here
}
and this is my BST class:
public class BinarySearchTree<T>: ICollection<T> where T: IComparable<T>
{
internal Node<T> Root { get; set; }
public int Count { get; private set; }
public bool IsReadOnly => false;
//some methods go here
}
Now in order to implement ICollection<T> i obviously need an enumerator which I have (partly) implemented as such:
internal class BinarySearchTreeEnumerator<T> : IEnumerator<T> where T: IComparable<T>
{
private BinarySearchTree<T> _parentTree;
private BinarySearchTree<T> _currentTree;
private Node<T> _currentNode => _currentTree.Root;
private T _currentKey;
public T Current => _currentNode.Key;
/// <summary>
/// generic constructor
/// </summary>
/// <param name="tree"></param>
public BinarySearchTreeEnumerator(BinarySearchTree<T> tree)
{
this._parentTree = tree;
}
object IEnumerator.Current => Current;
void IDisposable.Dispose(){}
//pls
public bool MoveNext()
{
if (_currentTree is null)
{
_currentTree = _parentTree;
}
var leftSubtree = this._currentTree.GetLeftSubtree();
var rightSubtree = this._currentTree.GetRightSubtree();
if (!(leftSubtree is null))
{
this._currentTree = leftSubtree;
}
else if (!(rightSubtree is null))
{
this._currentTree = rightSubtree;
}
else
{
}
}
public void Reset()
{
_currentTree = _parentTree;
}
}
now my issue is quite obviously with the MoveNext() method. It doesn't work now because what it does is it just goes down the tree on the leftmost possible path and then gets stuck when it gets to the end of that path. I know I can fix this problem by adding a Parent property to my Node<T> class and then whenever I reach the end of a path in my tree I can just go one Node up and check if there's a different path... However this would mean completely changing my original class and I would prefer not to do that.
Is this just unavoidable? Is there any way to solve this issue without changing my Node<T> class in such a way?
Edit: I Made a thing but its not working :/
public bool MoveNext()
{
if (_currentNode is null)
{
this._currentNode = _parentTree.Root;
this._nodeStack.Push(_currentNode);
return true;
}
var leftNode = this._currentNode.LeftChildNode;
var rightNode = this._currentNode.RightChildNode;
if (!(leftNode is null))
{
this._currentNode = leftNode;
this._nodeStack.Push(_currentNode);
return true;
}
else if (!(rightNode is null))
{
this._currentNode = rightNode;
this._nodeStack.Push(_currentNode);
return true;
}
else
{
//current node does not have children
var parent = this._nodeStack.Pop();
do
{
if (parent is null)
{
return false;
}
} while (!(parent.RightChildNode is null));
this._currentNode = parent.RightChildNode;
this._nodeStack.Push(_currentNode);
return true;
}
}

It might be easier to use recursion to implement this; for example:
Recursive version (for balanced trees only)
public IEnumerator<T> GetEnumerator()
{
return enumerate(Root).GetEnumerator();
}
IEnumerable<T> enumerate(Node<T> root)
{
if (root == null)
yield break;
yield return root.Key;
foreach (var value in enumerate(root.LeftChildNode))
yield return value;
foreach (var value in enumerate(root.RightChildNode))
yield return value;
}
These are members of BinarySearchTree<T>.
Given the above implementation, then the following code:
BinarySearchTree<double> tree = new BinarySearchTree<double>();
tree.Root = new Node<double> {Key = 1.1};
tree.Root.LeftChildNode = new Node<double> {Key = 2.1};
tree.Root.RightChildNode = new Node<double> {Key = 2.2};
tree.Root.LeftChildNode.LeftChildNode = new Node<double> { Key = 3.1 };
tree.Root.LeftChildNode.RightChildNode = new Node<double> { Key = 3.2 };
tree.Root.RightChildNode.LeftChildNode = new Node<double> { Key = 3.3 };
tree.Root.RightChildNode.RightChildNode = new Node<double> { Key = 3.4 };
foreach (var value in tree)
{
Console.WriteLine(value);
}
produces this output:
1.1
2.1
3.1
3.2
2.2
3.3
3.4
WARNING: Stack space is limited to 1MB for a 32-bit process and 4MB for a 64-bit process, so using recursion is likely to run out of stack space if the tree is degenerate (badly unbalanced).
Non-recursive version
You can implement the non-recursive version fairly simply, like so:
IEnumerable<T> enumerate(Node<T> root)
{
var stack = new Stack<Node<T>>();
stack.Push(root);
while (stack.Count > 0)
{
var node = stack.Pop();
if (node == null)
continue;
yield return node.Key;
stack.Push(node.RightChildNode);
stack.Push(node.LeftChildNode);
}
}
This returns the elements in the same order as the recursive version.
Since this version will not run out of stack space even for a degenerate tree, it is preferable to the recursive version.

If you add to your enumerator a
private List<Node<T>> _currentParentNodes = new List<Node<T>>();
and use it like a stack, each time you go down a level you push the current node to currentParentNodes, each time you have to go up you pop the parent node from currentParentNodes, then all your problems will pop away :-)

Do you need a depth-first-search(DFS) approach? It has a recursive nature which is hard to save as a state (it uses the call stack).
Maybe consider the broad-first-search (BFS) approach, which is iterative. You'd only need a currentNode and a Queue.
The rule would be
current = Queue.poll();
For child in current
Queue.offer(child);
At init you would do
Queue.offer(rootNode);
I apologize for my poor formatting and syntax, mobile user here.
Andres

Related

Set a maximum count for parent-child object initialization c#

TL;DR ?:(
hi, I'm creating a source generator, It's been a pain since I started TBH.
I have a class:
public class CsharpTypeBase
{
public CsharpTypeBase(int childCount = 0)
{
childCount++;
if (childCount < 5)
{
Child = new(childCount);
}
}
public bool IsSimple { get; set; }
public bool IsArray { get; set; }
public bool IsIEnumerable { get; set; }
public ref CsharpTypeBase? Child
{
get => ref _child;
}
public string? ValueIfIsSimple
{
get => _valueIfIsSimple;
set
{
IsSimple = true;
_valueIfIsSimple = value;
}
}
public CsharpClassModel ClassModel
{
get => _classModel;
set
{
IsSimple = false;
_classModel = value;
}
}
private string? _valueIfIsSimple;
private CsharpClassModel _classModel = new();
private CsharpTypeBase? _child;
}
which is a base class for other CSharp types that I have(ex: ReturnTypes,Parameters,Properties)
with the following code im trying to parse c# classes into simpler versions(and after that do something with them):
public static CsharpTypeBase Convert(TypeSyntax typeSyntax)
{
var output = new CsharpTypeBase();
FromTypeSyntax(typeSyntax,ref output);
return output;
}
private static void FromTypeSyntax(TypeSyntax typeSyntax,ref CsharpTypeBase output)
{
switch (typeSyntax)
{
case PredefinedTypeSyntax predefinedTypeSyntax:
output.ValueIfIsSimple = predefinedTypeSyntax.Keyword.ValueText;
output.IsIEnumerable = false;
output.IsArray = false;
break;
case IdentifierNameSyntax identifierNameSyntax:
CsharpClassModel.RecursivelyWalkThroughTheClass(identifierNameSyntax.Identifier.ValueText,output);
break;
case ArrayTypeSyntax arrayTypeSyntax:
output.IsArray = true;
output.IsIEnumerable = false;
FromTypeSyntax(arrayTypeSyntax.ElementType,ref output.Child!);
break;
case GenericNameSyntax genericNameSyntax:
var (innerClass,isEnumerable) = FindTheMostInnerType(genericNameSyntax);
output.IsIEnumerable = isEnumerable;
FromTypeSyntax(innerClass,ref output.Child!);
break;
}
}
as you can see it's a recursive function, and its doing just fine, the only problem I have with this design is (that Child property) it's not really memory friendly and stable because of my base class, by default it's creating 5 child class(which is the same type as my base, it's stupid but I cant thing of anything else).
I want this to be more efficient, what if I only need 2 children? or worse, what if I needed more children to be created? I need the Exact Count otherwise it will OverFlow (by creating infinite objects) or blow up:
FromTypeSyntax(arrayTypeSyntax.ElementType,ref output.Child!);
this code should somehow set a maximum count for :
Child = new();
And the reason I need that Child property is to parse/convert this kind of incoming types:
List<string>[] one,
List<string[]> two,
Task<List<IReadOnlyCollection<FirstDto>>> three,
AnotherDto[] four,
string five,
int[] six,
List<List<List<List<List<List<string>>>>>> seven
Thank you for reading this question.
I solved My problem by making the Child object nullable:
public CsharpTypeBase? Child { get;set; }
and using it like this :
FromTypeSyntax(child, output.Child ??= new());

C# How to pool the objects of a node tree efficiently?

I have a node class that contains only value type properties, and one reference type: it's parent node. When performing tree searches, these nodes are created and destroyed hundreds of thousands of times in a very short time span.
public class Node
{
public Node Parent { get; set; }
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }
public int D { get; set; }
}
The tree search looks something like this:
public static Node GetDepthFirstBest(this ITree tree, Node root)
{
Node bestNode = root;
float bestScore = tree.Evaluate(root);
var stack = new Stack<Node>();
stack.Push(root);
while(stack.Count > 0)
{
var current = stack.Pop();
float score = tree.Evaluate(current);
if (score > bestScore)
{
bestNode = current;
bestScore = score;
}
var children = tree.GetChildren(current);
foreach(var c in children) { stack.Push(c); }
}
return bestNode;
}
Because this is done in a Mono runtime that has a very old GC, I wanted to try and pool the node objects. However, I am at a loss on how to know when a node object is safe to return to the pool, since other nodes that are still in use might reference it as a parent. At the end of the search, the best node is returned and a list of nodes is formed by walking back through its ancestors. I have full control over how the nodes are created inside the tree, if that's useful.
What options could I try and implement?
So, fortunately, if you're doing a Depth-First-Search, which you appear to be, this is a bit easier. Any time you reach a leaf node, there are two possibilities: that leaf node is part of the current deepest tree, or it's not.
If it's not, that means it's safe to return this node to the pool. If it is, that means we can return any nodes in our old tree back to our pool that are not in our own ancestor chain.
Now, if we're not a leafnode, we don't know if we can be freed until after we've finished checking our children. then, once all our children are checked, we find out if any of our children said they were the current best. if so, we keep ourselves
this does mean we're doing quite a bit more checking.
Here's some sudo code:
List bestNodes;
bool evalNode(node, score)
{
if (childCount == 0)
{
if (score > bestScore)
{
bestScore = score;
bestNode = node;
bestNodes.Add(node);
return true;
}
else
{
freeNode(this);
return false;
}
}
else
{
bool inLongest = false;
foreach (child in children)
{
inLongest = evalNode(child, score + 1) || inLongest;
}
if (!inLongest)
{
freeNode(node);
}
else
{
free(bestNodes[score]);
bestNodes[score] = node;
}
return inLongest;
}
}
Try using the ref keyword if your node is a struct, this avoids copying the node every time you pass it through to a function.
Thus:
struct Node
{
object obj;
Node children;
}
public void DoStuffWithNode(ref Node pNode){...Logic...}

Getting the father-children relationships

Let's say we have a Windows app that has a TreeView and you can expand the nodes of this view and drill down to the children node, they may also have more children so now we can expand that node and go further, etc.. So in my source code I have a method Foo(string fatherNode) that gets the father node that we clicked on and finds the children and lists them:
the high level body of this method is like this:
private void Foo(string fatherNode)
{
// call some DB scripts and grab data you need to work with.
int numberOfKids = // get it from the thing you populated from the DB call.
for(int i = 1 to numberOfKids)
{
Node Child = // grab child[i] from the list we populated from DB calls
//Add it to the treeView
}
}
Well that code is good for a UI app, where we click on a node, it runs this method once and collects the data it needs, Now I need to write another method utilizing useful lines of the method above Grab EVERYTHING at once and write the Whole information to let's say a file.
So in my head in looks like a recursive method to me. But still can't figure out the whole picture, Prob should have two collections, one for fathers, one for kids, loop through kids and make recursive call to get more kids and add them to the collection, etc
I was wondering if you can clear out the fogs, the high-level of what I need to do to, how the colections should look like, where to add to them, where to call the recursive method call, etc...and please don't specifically think about a "treeview" object, I just used that as an example to expalin the question better. The main thing is the structure of the Foo method that I posted. That's what I should work with.
Well, I'm not sure if this is what you're looking for, even after the other answers.
However, please, check it out:
The self-related entity (Node)
public class MyEntity
{
public MyEntity() { }
public MyEntity(string Name, int ID, int? ParentID)
{
this.Name = Name;
this.ID = ID;
this.ParentID = ParentID;
}
public string Name { get; set; }
public int ID { get; set; }
public int? ParentID { get; set; }
}
The tree building methods
public static StringBuilder GetFamilyTree(List<MyEntity> AllTheEntities)
{
StringBuilder Return = new StringBuilder();
List<MyEntity> OrderedEntities = AllTheEntities.OrderBy<MyEntity, int>(x => x.ID).ToList();
foreach (MyEntity CurrentEntity in AllTheEntities.Where<MyEntity>(x => !x.ParentID.HasValue))
{
Return.AppendLine(GetEntityTree(AllTheEntities, CurrentEntity));
}
return Return;
}
public static string GetEntityTree(List<MyEntity> AllTheEntities, MyEntity CurrentEntity, int CurrentLevel = 0)
{
StringBuilder Return = new StringBuilder();
Return.AppendFormat("{0}{1}", "\t".Repeat(CurrentLevel), CurrentEntity.Name);
Return.AppendLine();
List<MyEntity> Children = AllTheEntities.Where<MyEntity>(x => x.ParentID.HasValue && x.ParentID.Value == CurrentEntity.ID).ToList();
if (Children != null && Children.Count > 0)
{
foreach (MyEntity CurrentChildEntity in Children)
{
Return.Append(GetEntityTree(AllTheEntities, CurrentChildEntity, CurrentLevel + 1));
}
}
return Return.ToString();
}
A small helper class
public static class StringExtension
{
public static string Repeat(this string text, int times)
{
string Return = string.Empty;
if (times > 0)
{
for (int i = 0; i < times; i++)
{
Return = string.Concat(Return, text);
}
}
return Return;
}
}
Usage
List<MyEntity> AllMyEntities = new List<MyEntity>();
AllMyEntities.Add(new MyEntity("1", 1, null));
AllMyEntities.Add(new MyEntity("1.1", 2, 1));
AllMyEntities.Add(new MyEntity("1.1.1", 3, 2));
AllMyEntities.Add(new MyEntity("2", 4, null));
AllMyEntities.Add(new MyEntity("2.1", 5, 4));
Console.Write(GetFamilyTree(AllMyEntities).ToString());
Results
1
1.1
1.1.1
2
2.1
Call Foo(child) within for loop. I guess that will solve your problem. If tree is huge don't recurse. Use Stack.
You want to make a simple tree traversal algorithm. Here is a simple implementation of a DFS (Depth first search) in pseudo code:
TraverseTree(Tree t)
{
DoSomethingWith(t); // like writing the contents of the node to the file.
if (t == null) // leaf
return;
foreach(Tree child in t.Children) // recursively traverse the children.
{
TraverseTree(child);
}
}
You can play with the order you execute your computation. see more details here

Loop detection in LinkedList using C#

In the interview question, "Implement an algorithm which detects for presence of the loop.". For example, the linked list has a loop, like:
0--->1---->2---->3---->4---->5---->6
▲ |
| ▼
11<—-22<—-12<—-9<—-8
Using Floyd's cycle detection, this problem can be solved by using a fast & slow pointer. So should I try comparing
a. Link's node values, i.e.
if (fast.data == slow.data)
break;
where fast and slow are of type Link
class Link
{
int IData {get; set;}
Link Next {get; set;}
}
OR
b. Are they pointing to same reference, i.e. if (fast == slow)
Thanks.
You should only be comparing the nodes themselves. After all, it's reasonable to have a linked list with repeated data in, without it actually having a cycle.
I would call them nodes rather than links too. A link is simply the reference from one node to the next or previous one - in particular, there's no data associated with a link, only with a node.
Hope this helps... It might be naive but it works...
using System;
namespace CSharpTestTemplates
{
class LinkedList
{
Node Head;
public class Node
{
public int value;
public Node NextNode;
public Node(int value)
{
this.value = value;
}
}
public LinkedList(Node head)
{
this.Head = head;
}
public Boolean hasLoop()
{
Node tempNode = Head;
Node tempNode1 = Head.NextNode;
while(tempNode!=null && tempNode1!=null){
if(tempNode.Equals(tempNode1)){
return true;
}
if ((tempNode1.NextNode != null) && (tempNode.NextNode != null))
{
tempNode1 = tempNode1.NextNode.NextNode;
tempNode = tempNode.NextNode;
}
else
{
return false;
}
}
return false;
}
public static void Main()
{
Node head = new Node(1);
LinkedList ll = new LinkedList(head);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
Node node6 = new Node(6);
head.NextNode = node2;
node2.NextNode = node3;
node3.NextNode = node4;
node4.NextNode = node5;
node5.NextNode = node6;
node6.NextNode = null;
Console.WriteLine(ll.hasLoop());
Console.Read();
}
}
}

Recursively search nested lists

I've read and searched and I'm yet to figure out an answer to this relatively simple issue.
I have a class:
public class AccessibleTreeItem
{
public string name;
public List<AccessibleTreeItem> children;
public AccessibleTreeItem()
{
children = new List<AccessibleTreeItem>();
}
}
which is populate using a series of functions that don't really matter in this context, but what I'm looking for is a way to search through ALL of the children items in the list, searching for a particular 'name' value, and if found, returning that List.
How is this achieved in the easiest manner, with the least performance hit? Thanks - I've been stumped at this point for days now...
public class AccessibleTreeItem
{
public string name;
public List<AccessibleTreeItem> children;
public AccessibleTreeItem()
{
children = new List<AccessibleTreeItem>();
}
public static AccessibleTreeItem Find(AccessibleTreeItem node, string name)
{
if (node == null)
return null;
if (node.name == name)
return node;
foreach (var child in node.children)
{
var found = Find(child, name);
if (found != null)
return found;
}
return null;
}
}

Categories