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.
Related
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.
How do I do a depth first search using a Queue in c#?
The following is my datastructure:
public class Node
{
public string Name{get;set}
public IEnumerable<Node> Children{get;set;}
}
Now I have a collection of Node object each with children, which again has children and so on.
I want to access each node and convert it into a different form.
Something like the below:
public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes)
{
var queue = new Queue<Node>(nodes);
while (queue.Any())
{
var next = queue.Dequeue();
yield return BuildContentFromSingle(next);
foreach (var child in next.Children)
{
queue.Enqueue(child);
}
}
}
public IContent BuildContentFromSingle(Node node)
{
var content = _contentFactory.Create(node);
return content;
}
The above does not give me depth first for some reason. Can you please help?
Depth-first search is implemented using a LIFO data structure, so you 'd need to swap the Queue for a Stack. Using a FIFO structure like a queue gives you BFS instead.
you can do it recursively
public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes) {
foreach(var node in nodes){
yield node;
foreach(var c in BuildContentFrom(node.children)){
yield c;
}
}
}
This might become a problem with n-trees when n is large and/or the tree deep.
in which case you could use an accumulator
public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes) {
if(!nodes.Any()) return Enumerable.Empty<IContent>();
var acc = new List<IContent>();
BuildContentFrom(nodes);
}
public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes,
IList<IContent> acc) {
foreach(var node in nodes){
acc.Add(BuildContentFromSingle(node));
if(node.children.Any()) BuildContentFrom(node.children, acc);
}
}
Which is now tail recursive and if the compiler optimizes for that (a setting for C# as far as I remember) you will have no stack issues even with large trees.
Alternatively you can use a stack to collect the work you still need to perform
public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes)
{
var stack= new Stack<Node>(nodes);
while (stack.Any())
{
var next = stack.Pop();
yield return BuildContentFromSingle(next);
foreach (var child in next.Children)
{
stack.push(child);
}
}
}
As an alternative, you could consider flattening the structure using recursion. Here's an example with a binary tree. It demonstrates a depth-first flattening traversal.
using System;
using System.Collections.Generic;
namespace Demo
{
public static class Program
{
static void Main(string[] args)
{
var tree = buildTree(5, true);
printTree1(tree);
Console.WriteLine("---------------------------------------------");
printTree2(tree);
}
// Print tree using direct recursion.
static void printTree1<T>(Node<T> tree)
{
if (tree != null)
{
Console.WriteLine(tree.Value);
printTree1(tree.Left);
printTree1(tree.Right);
}
}
// Print tree using flattened tree.
static void printTree2<T>(Node<T> tree)
{
foreach (var value in flatten(tree))
{
Console.WriteLine(value);
}
}
// Flatten tree using recursion.
static IEnumerable<T> flatten<T>(Node<T> root)
{
if (root == null)
{
yield break;
}
foreach (var node in flatten(root.Left))
{
yield return node;
}
foreach (var node in flatten(root.Right))
{
yield return node;
}
yield return root.Value;
}
static Node<string> buildTree(int depth, bool left)
{
if (depth > 0)
{
--depth;
return new Node<string>(buildTree(depth, true), buildTree(depth, false), "Node." + depth + (left ? ".L" : ".R"));
}
else
{
return new Node<string>(null, null, "Leaf." + (left ? "L" : "R"));
}
}
}
public sealed class Node<T>
{
public Node(Node<T> left, Node<T> right, T value)
{
_left = left;
_right = right;
_value = value;
}
public Node<T> Left { get { return _left; } }
public Node<T> Right { get { return _right; } }
public T Value { get { return _value; } }
private readonly Node<T> _left;
private readonly Node<T> _right;
private readonly T _value;
}
}
For your specific example, I think (without testing it) that you can do this:
public static IEnumerable<Node> Flatten(Node root)
{
foreach (var node in root.Children)
{
foreach (var child in Flatten(node))
{
yield return child;
}
}
yield return root;
}
Depending on whether you allow null nodes, you might need to add some null checking:
public static IEnumerable<Node> Flatten(Node root)
{
if (root != null)
{
foreach (var node in root.Children)
{
foreach (var child in Flatten(node))
{
if (child != null)
{
yield return child;
}
}
}
yield return root;
}
}
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;
}
}
}
}
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);
}