I have been struggling for days finding .NET Tree Data Structure, I have read many recomendation using C5 library, but I have yet find example for it.
I have read C5 documentation but didn't find example for it (I admit I haven't read all documentation page).
Edit: I need a Tree with basic functionality like search from parent to child node and vice versa.
If you need only tree datastructure, just define yours. (will loose less time)
public abstract class NodeAbstract
{
abstract NodeAbstract Left {get;set:}
abstract NodeAbstract Right {get;set:}
....
....
}
public class NodeConcrete : NodeAbstract
{
....
//implementation
}
If you only need the most basic functionality, then build your own data structure.
I did a quick implementation of a basic tree (directional edges and not necessarily binary tree), assuming you have a fixed root node. I also added methods for searching depth first and breadth first.
using System;
using System.Collections.Generic;
namespace TreeTest
{
class Program
{
static void Main(string[] args)
{
//Build example tree
Tree tree = new Tree();
Node a = new Node(2);
Node b = new Node(7);
Node c = new Node(2);
Node d = new Node(6);
Node e = new Node(5);
Node f = new Node(11);
Node g = new Node(5);
Node h = new Node(9);
Node i = new Node(4);
tree.rootNode = a;
a.Edges.Add(b);
b.Edges.Add(c);
b.Edges.Add(d);
d.Edges.Add(e);
d.Edges.Add(f);
a.Edges.Add(g);
g.Edges.Add(h);
h.Edges.Add(i);
//Find node scannin tree from top down
Node node = tree.FindByValueBreadthFirst(6);
Console.WriteLine(node != null ? "Found node" : "Did not find node");
//Find node scanning tree branch for branch.
node = tree.FindByValueDepthFirst(2);
Console.WriteLine(node != null ? "Found node" : "Did not find node");
Console.WriteLine("PRESS ANY KEY TO EXIT");
Console.ReadKey();
}
}
class Tree
{
public Node rootNode;
public Node FindByValueDepthFirst(int val)
{
return rootNode.FindRecursiveDepthFirst(val);
}
public Node FindByValueBreadthFirst(int val)
{
if (rootNode.Value == val)
return rootNode;
else
return rootNode.FindRecursiveBreadthFirst(val);
}
}
class Node
{
public int Value { get; set; }
public IList<Node> Edges { get; set; }
public Node(int val)
{
Value = val;
Edges = new List<Node>(2);
}
public Node FindRecursiveBreadthFirst(int val)
{
foreach (Node node in Edges)
{
if (node.Value == val)
return node;
}
foreach (Node node in Edges)
{
Node result = node.FindRecursiveBreadthFirst(val);
if (result != null)
return result;
}
return null;
}
public Node FindRecursiveDepthFirst(int val)
{
if (Value == val)
return this;
else
{
foreach (Node node in Edges)
{
Node result = node.FindRecursiveDepthFirst(val);
if (result != null)
return result;
}
return null;
}
}
}
}
Related
I have this binary search tree with Node class and I need to write mapping and filtering method for it but I have no clue how can I go through the whole tree. My every attempt to go through it skipped almost half of the tree.
public class BST<T> where T:IComparable<T>
{
public class Node
{
public T value { get; }
public Node left;
public Node right;
public Node(T element)
{
this.value = element;
left = null;
right = null;
}
}
private Node root;
private void add(T element)
{
if (root == null)
root = new Node(element);
else
{
add(element, root);
}
}
public void add(T element, Node leaf)
{
if(element.CompareTo(leaf.value) > 0)
{
if (leaf.right == null)
leaf.right = new Node(element);
else
add(element,leaf.right);
}
else
{
if (leaf.left == null)
leaf.left = new Node(element);
else
add(element, leaf.left);
}
}
}
I have no clue how can I go through the whole tree
There are many ways to do that. One is to make your class iterable.
For that you can define the following method on your Node class:
public IEnumerator<T> GetEnumerator()
{
if (left != null) {
foreach (var node in left) {
yield return node;
}
}
yield return value;
if (right != null) {
foreach (var node in right) {
yield return node;
}
}
}
And delegate to it from a similar method on your BST class:
public IEnumerator<T> GetEnumerator()
{
if (root != null) {
foreach (var node in root) {
yield return node;
}
}
}
Now you can write code like this:
var tree = new BST<int>();
tree.add(4);
tree.add(2);
tree.add(3);
tree.add(6);
tree.add(5);
foreach (var value in tree) {
Console.WriteLine(value);
}
I need to write mapping and filtering method for it
It depends on what you want the result of a mapping/filtering function to be. If it is just a sequence of values, the above should be simple to adapt. If a new tree should be created with the mapped/filtered values, then feed these values back into a new tree (calling its add), or (in case of mapping) use the same recursive pattern of the above methods to create a new method that does not do yield, but creates a new tree while iterating the existing nodes, so the new tree has the same shape, but with mapped values.
Can someone please tell me what i need to put in place of the '//code missing here'?
Where i have put "code missing" is where i am stuck. I am not sure what i need to put in place. I am new to binary trees so unfortunately am not very experienced with how they work. For my assignment this is the format my teacher wants so other tutorials online have not been particularly useful
using System;
public class Program
{
public class binarytree
{
public class node
{ // Single element of tree (node)
public string data;
public node //CODE MISSING HERE
public node rightPointer;
}
public node root;
public bool add(string item)
{
try //in case of memory overflow (full)
{
// store new item in memory and start looking from root of tree
node newNode = new node();
newNode.data = item;
newNode.//CODE MISSING HERE
newNode.rightPointer = //CODE MISSING HERE
node currentNode = root;
//Case that tree is empty
if (currentNode == null)
{
root = newNode;
return true;
}
else
{
//work out where to put new item, by traversing tree until we find a left
node previous = currentNode;
while (currentNode != null)
{
previous = currentNode;
//compareTo compares two strings, returns val <0 if lower
if (item.CompareTo(currentNode.data) //CODE MISSING HERE
{
currentNode = //CODE MISSING HERE
}
else
{
currentNode = currentNode.rightPointer;
}
}
if (item.CompareTo(previous.data)<0)
{
//CODE MISSING HERE
}
else
{
previous.rightPointer = newNode;
}
return true;
}
}
catch
{
return false;
}
}
}
public static void Main()
{
binarytree bt = new binarytree();
bt.add("I am root");
bt.add("Avengers");
bt.add("Marvel");
Console.WriteLine(bt.root.data);
Console.WriteLine(bt.root.//CODE MISSING HERE
Console.WriteLine(bt.root.rightPointer.data);
}
}
I have sorted it
using System;
public class Program
{
public class binarytree
{
public class node
{ // Single element of tree (node)
public string data;
public node leftPointer;
public node rightPointer;
}
public node root;
public bool add(string item)
{
try //in case of memory overflow (full)
{
// store new item in memory and start looking from root of tree
node newNode = new node();
newNode.data = item;
newNode.leftPointer = null;
newNode.rightPointer = null;
node currentNode = root;
//Case that tree is empty
if (currentNode == null)
{
root = newNode;
return true;
}
else
{
//work out where to put new item, by traversing tree until we find a left
node previous = currentNode;
while (currentNode != null)
{
previous = currentNode;
//compareTo compares two strings, returns val <0 if lower
if (item.CompareTo(currentNode.data)<0)
{
currentNode = currentNode.leftPointer;
}
else
{
currentNode = currentNode.rightPointer;
}
}
if (item.CompareTo(previous.data)<0)
{
previous.leftPointer = newNode;
}
else
{
previous.rightPointer = newNode;
}
return true;
}
}
catch
{
return false;
}
}
}
public static void Main()
{
binarytree bt = new binarytree();
bt.add("I am root");
bt.add("Avengers");
bt.add("Marvel");
Console.WriteLine(bt.root.data);
Console.WriteLine(bt.root.leftPointer.data);
Console.WriteLine(bt.root.rightPointer.data);
}
}
Generic implementation in C#. A very quick example, so obviously the code can be improved quite a bit, however at the moment I want to get it to work in its current form.
Adding new nodes, or deleting existing ones, does not work. When the print() method is called in the driver program:
BinarySearchTree<int> testTree = new BinarySearchTree<int>(1);
Console.WriteLine("Binary search tree contains 0: " + testTree.exists(0));
Console.WriteLine("Binary search tree contains 1: " + testTree.exists(1));
Console.WriteLine("Binary search tree contains 2: " + testTree.exists(2));
testTree.add(2);
Console.WriteLine("Binary search tree contains 2: " + testTree.exists(2));
testTree.remove(1);
Console.WriteLine("Binary search tree contains 1: " + testTree.exists(1));
testTree.print();
Console output for the above:
Binary search tree contains 0: False
Binary search tree contains 1: True
Binary search tree contains 2: False
Binary search tree contains 2: False
Binary search tree contains 1: True
1
Checked with setting breakpoints at the appropriate methods, no closer to finding the problem.
Code for this class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace BinaryTree
{
public class BinarySearchTree<T> where T : IComparable
{
#region private members
private class Node
{
public T value;
public Node left;
public Node right;
}
private Node rootNode;
private void insert(Node root, Node node)
{
if (root==null)
{
root = node;
}
else if (isLessThan(node.value,root.value))
{
insert(node.left, node);
}
else if (isGreaterThan(node.value,root.value) || (isEqual(root.value,node.value)))
{
insert(node.right, node);
}
}
private void displayInOrder(Node node)
{
if (node != null)
{
displayInOrder(node.left);
Console.WriteLine(node.value);
displayInOrder(node.right);
}
}
#region comparison helper functions
private bool isGreaterThan(T a, T b)
{
return a.CompareTo(b) > 0;
}
private bool isLessThan(T a, T b)
{
return a.CompareTo(b) < 0;
}
private bool isEqual(T a, T b)
{
return a.CompareTo(b) == 0;
}
#endregion
#endregion
// ctor
public BinarySearchTree(T rootValue)
{
rootNode = new Node();
rootNode.value = rootValue;
rootNode.left = null;
rootNode.right = null;
}
public void add(T value)
{
// first create a new node. Eventually, it will be added to the tree.
Node newNode = new Node();
newNode.value = value;
newNode.left = null;
newNode.right = null;
// give this node to the insert method, which will traverse the tree until it finds the correct place to insert it.
insert(rootNode, newNode);
}
public bool exists(T value)
{
Node node = rootNode;
while (node!=null)
{
if (isEqual(node.value,value))
{
return true;
}
else if (isLessThan(value,node.value))
{
node = node.left;
}
else if (isGreaterThan(value,node.value))
{
node = node.right;
}
}
return false;
}
public void remove(T value)
{
Node node = rootNode;
while (node!=null)
{
if (isEqual(node.value,value))
{
node = null;
}
else if (isLessThan(node.value, value))
{
node = node.left;
}
else if (isGreaterThan(node.value, value) || (isEqual(value, node.value)))
{
node = node.right;
}
}
}
public void print()
{
displayInOrder(rootNode);
}
}
}
Your problem is that you are assigning a value to a null, which is not a reference at all.
The null keyword is a literal that represents a null reference, one that does not refer to any object. null is the default value of reference-type variables. Ordinary value types cannot be null, except for nullable value types.
In this line of code node.right has the value null.
insert(node.right, node);
So you will assign node to a null which is no reference at all.
My suggestion would be to change the insert code like this:
Declare a direction enum
public enum Direction {
Left,
Right
}
Use the enum to update the proper reference
private void insert(Node root, Node node)
{
if (root==null)
{
root = node;
}
else if (isLessThan(node.value,root.value))
{
insert(root, node, Direction.Left);
}
else if (isGreaterThan(node.value,root.value) || (isEqual(root.value,node.value)))
{
insert(root, node, Direction.Right);
}
}
private void insert(Node root, Node node, Direction direction)
{
if (direction == Direction.Left)
{
// You are actually updating the reference left of root node
root.left = node;
}
else if (direction == Direction.Right)
{
// You are actually updating the reference right of root node
root.right = node;
}
}
The remove logic is pretty much the same. Check the comments
// I am declaring a local reference to a Node
Node node = rootNode;
while (node!=null)
{
if (isEqual(node.value,value))
{
// I am updating the local reference to null
// I am not setting the left or right value reference to null
// So that I won't be able to find it again
node = null;
}
Beware that when you detach one reference, you have to rebuild the whole tree. If you detach a link by setting null on the left, then all the left values will be detached as well.
In C#, how can i search a hierarchy list and also keep the path intact at the end. For example:
The object
public class Node
{
public IEnumerable<Node> Children { get; set; }
public string Id { get; set; }
}
Result
a
aa
aaa
aab
b
ba
bb
bba
What i want
If i search this list for the word "aab", i would like to show this result to the client:
a
aa
aab
One implementation that i've found to search a hierarchy list is this one taken there https://stackoverflow.com/a/30907231/316759 but the problem is that it only return the leaf nodes found without keeping the hierarchy structure.
public static T DepthFirstSearch<T, TChilds>(this T node, Func<T, TChilds> ChildsProperty, Predicate<T> Match) where T : class
{
Stack<T> stack = new Stack<T>();
stack.Push(node);
while (stack.Count > 0)
{
T thisNode = stack.Pop();
if (Match(thisNode))
{
return thisNode;
}
if (ChildsProperty(thisNode) != null)
{
foreach (T child in (ChildsProperty(thisNode) as IEnumerable<T>).Reverse())
{
stack.Push(child);
}
}
}
return null;
}
What i need is to find leaf nodes and keep their parents to the root.
Here's a quick example that will let you mark the nodes you want as shown:
public bool NodeOrChildrenMatch(Node n)
{
if (IsMatch(n))
{
Show(n);
return true;
}
else
{
if (n.Children.Any(NodeOrChildrenMatch))
{
Show(n);
return true;
}
return false;
}
}
Approximate code - collect "path" while going down recursively and clean up last element while going up:
Stack<T> path = new Stack<T>();
public static bool DepthFirstSearch(T node, Stack<T> path, Predicate<T> Match)
{
path.Push(node);
if (Match(node))
return true;
foreach (T child in (thisNode.Children)
{
if (DepthFirstSearch(child, stack, Match))
return true;
}
stack.Pop();
return false;
}
I was trying to solve one interview question, but for that I have to travel the binary tree level by level. I have designed BinaryNode with having below variable
private object data;
private BinaryNode left;
private BinaryNode right;
Could someone please help to write the BreadthFirstSearch method inside my BinarySearchTree class?
Update: Thanks everyone for your inputs. So this was the interview question.
"Given a binary search tree, design an algorithm which creates a linked list of all the nodes at each depth (i.e., if you have a tree with depth D, you’ll have D linked lists)".
Here is my Method, let me know your expert comment.
public List<LinkedList<BNode>> FindLevelLinkList(BNode root)
{
Queue<BNode> q = new Queue<BNode>();
// List of all nodes starting from root.
List<BNode> list = new List<BNode>();
q.Enqueue(root);
while (q.Count > 0)
{
BNode current = q.Dequeue();
if (current == null)
continue;
q.Enqueue(current.Left);
q.Enqueue(current.Right);
list.Add(current);
}
// Add tree nodes of same depth into individual LinkedList. Then add all LinkedList into a List
LinkedList<BNode> LL = new LinkedList<BNode>();
List<LinkedList<BNode>> result = new List<LinkedList<BNode>>();
LL.AddLast(root);
int currentDepth = 0;
foreach (BNode node in list)
{
if (node != root)
{
if (node.Depth == currentDepth)
{
LL.AddLast(node);
}
else
{
result.Add(LL);
LL = new LinkedList<BNode>();
LL.AddLast(node);
currentDepth++;
}
}
}
// Add the last linkedlist
result.Add(LL);
return result;
}
A breadth first search is usually implemented with a queue, a depth first search using a stack.
Queue<Node> q = new Queue<Node>();
q.Enqueue(root);
while(q.Count > 0)
{
Node current = q.Dequeue();
if(current == null)
continue;
q.Enqueue(current.Left);
q.Enqueue(current.Right);
DoSomething(current);
}
As an alternative to checking for null after dequeuing you can check before adding to the Queue. I didn't compile the code, so it might contain some small mistakes.
A fancier (but slower) version that integrates well with LINQ:
public static IEnumerable<T> BreadthFirstTopDownTraversal<T>(T root, Func<T, IEnumerable<T>> children)
{
var q = new Queue<T>();
q.Enqueue(root);
while (q.Count > 0)
{
T current = q.Dequeue();
yield return current;
foreach (var child in children(current))
q.Enqueue(child);
}
}
Which can be used together with a Children property on Node:
IEnumerable<Node> Children { get { return new []{ Left, Right }.Where(x => x != null); } }
...
foreach(var node in BreadthFirstTopDownTraversal(root, node => node.Children))
{
...
}
var queue = new Queue<BinaryNode>();
queue.Enqueue(rootNode);
while(queue.Any())
{
var currentNode = queue.Dequeue();
if(currentNode.data == searchedData)
{
break;
}
if(currentNode.Left != null)
queue.Enqueue(currentNode.Left);
if(currentNode.Right != null)
queue.Enqueue(currentNode.Right);
}
using DFS approach: The tree traversal is O(n)
public class NodeLevel
{
public TreeNode Node { get; set;}
public int Level { get; set;}
}
public class NodeLevelList
{
private Dictionary<int,List<TreeNode>> finalLists = new Dictionary<int,List<TreeNode>>();
public void AddToDictionary(NodeLevel ndlvl)
{
if(finalLists.ContainsKey(ndlvl.Level))
{
finalLists[ndlvl.Level].Add(ndlvl.Node);
}
else
{
finalLists.Add(ndlvl.Level,new List<TreeNode>(){ndlvl.Node});
}
}
public Dictionary<int,List<TreeNode>> GetFinalList()
{
return finalLists;
}
}
The method that does traversal:
public static void DFSLevel(TreeNode root, int level, NodeLevelList nodeLevelList)
{
if(root == null)
return;
nodeLevelList.AddToDictionary(new NodeLevel{Node = root, Level = level});
level++;
DFSLevel(root.Left,level,nodeLevelList);
DFSLevel(root.Right,level,nodeLevelList);
}