Algorithm to Clone a Graph in C# [duplicate] - c#

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 3 years ago.
Given a reference of a node in a connected undirected graph, return a deep copy (clone) of the graph. Each node in the graph contains a val (int) and a list (List[Node]) of its neighbors.
What is the mistake in this code - Clone a graph . It says
Object Reference not set to an instance of an object in LeetCode for
this line - target.Add(C);.
Could someone share some suggestions here.
public class Node {
public int val;
public IList<Node> neighbors;
public Node(){}
public Node(int _val,IList<Node> _neighbors) {
val = _val;
neighbors = _neighbors;}
public class Solution {
public Node CloneGraph(Node node) {
if (node == null)
{return null;}
var map = new Dictionary<int, Node>();
Queue<Node> q = new Queue<Node>();
q.Enqueue(node);
Node newNode = new Node();
newNode.val = node.val;
CopyList(node.neighbors,newNode.neighbors);
map.Add(newNode.val, newNode);
while(q.Count!=0)
{
Node head = q.Dequeue();
Node cloneU = map[head.val];
foreach (Node neighborNode in head.neighbors)
{
if(map.ContainsKey(neighborNode.val))
{
CopyList(head.neighbors,cloneU.neighbors);
}
else
{
q.Enqueue(neighborNode);
Node neighborNodeCopy = new Node(neighborNode.val,neighborNode.neighbors);
map.Add(neighborNodeCopy.val, neighborNodeCopy);
CopyList(neighborNodeCopy.neighbors,cloneU.neighbors);
}
}
}
return newNode;
}
public void CopyList(IList<Node> source, IList<Node> target)
{
foreach( Node C in source)
{
target.Add(C);
}
}
}

The specific error you're seeing is due to the fact that target is null, and you're trying to call a method (Add) on it.
To fix this, you can just set target to a new list if it's null before you try to call the .Add method on it:
public void CopyList(IList<Node> source, IList<Node> target)
{
if (target == null) target = new List<Node>();
foreach( Node C in source)
{
target.Add(C);
}
}
However, this is identical to a one-line version of the code, using the System.Linq extension method, ToList"
public void CopyList(IList<Node> source, IList<Node> target)
{
target = source?.ToList();
}
With that being said, it appears that you're trying to make a deep copy of Node, but when you do target.Add(C);, you're adding a reference to the source node instead of a clone of that node.
For deep copying, we need to make a complete copy of all reference types, and in the case of Node, the only reference type it has is the IList<Node> collection. A possibly more simple way to create a deep copy is to implement a Clone method on Node itself, which creates a new Node and then creates a new List<Node> that contains clones of each node in the list:
public class Node
{
public int Value { get; set; }
public IList<Node> Neighbors { get; set; }
public Node() { }
public Node(int val, IList<Node> neighbors)
{
Value = val;
Neighbors = neighbors;
}
public Node Clone()
{
// Start with a new node with the same value
var newNode = new Node { Value = Value };
// Deep copy the list of neighbors by returning their clones in a new list
newNode.Neighbors = Neighbors?.Select(node => node.Clone()).ToList();
// Return our deep copy
return newNode;
}
}

Related

Mapping binary search tree

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.

LinkedList Implementation Bug

I tried to implement my linked list below, It just that when I used my linked list, it seems that it's inserting a null entry in the middle. Anyone could take a look? The problem could be in the add end method.
LinkedList<T>
public class LinkedList<T> : IEnumerable<T>
{
public Node<T> Head { get; set; }
public int Count { get; set; }
public LinkedList()
{
Head = new Node<T>();
}
public void AddStart(T data)
{
if (Head == null)
{
Head = new Node<T> {Value = data};
}
else
{
var newNode = new Node<T> {Value = data, Next = Head};
Head = newNode;
}
Count++;
}
public void AddEnd(T data)
{
var newNode = new Node<T> { Value = data, Next = null};
var current = Head;
if (Head == null)
{
Head = newNode;
}
else
{
while (current.Next != null)
{
current = current.Next;
}
current.Next = newNode;
}
}
public IEnumerator<T> GetEnumerator()
{
Node<T> current = Head;
while (current != null)
{
yield return current.Value;
current = current.Next;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Usage:
LinkedList<string> strings = new LinkedList<string>();
strings.AddStart("a");
strings.AddStart("b");
strings.AddStart("c");
strings.AddEnd("a");
strings.AddEnd("e");
strings.AddEnd("d");
Result: (Notice the null in the middle)
c
b
a
a
e
d
Usage:
LinkedList<string> strings = new LinkedList<string>();
strings.AddStart("a");
strings.AddStart("b");
strings.AddStart("c");
strings.AddEnd("a");
strings.AddEnd("e");
strings.AddEnd("d");
strings.AddStart("a");
strings.AddEnd("b");
strings.AddStart("a");
strings.AddStart("b");
strings.AddStart("c");
strings.AddEnd("a");
strings.AddEnd("e");
strings.AddEnd("d");
Result: (Notice the null in the middle)
c
b
a
a
c
b
a
a
e
d
b
a
e
d
You are creating an empty Node, when you initialize your LinkedList:
public LinkedList()
{
Head = new Node<T>();
}
At this point you essentially have a node without a value. This is displayed as an empty value.
Everytime you call AddStart, you insert items before hand. When calling AddEnd you insert items at the end. Since you call both methods equally, it appears that the initial node is in the middle.
You can resolve this by changing your constructor to this:
public LinkedList()
{
Head = null;
}
Or by removing the constructor alltogether. In both methods you are checking for a Head node with a value, so you do not need to initialize it without a value.
if (Head == null)
{
Head = new Node<T> {Value = data};
}
In your current state, you are checking if Head is null. Head is of Type Node, which, if it is a class, cannot be null, if you initialize it in your constrcutor (Head = new Node<T>(); //not null any longer). So you need to make up your mind on how you want to solve it.
Personally I'd just write a unit test to assert my logic and implementation is correct. If you assume that Head is null after initialisation, test for it:
[Fact]
public void AssertHeadIsNull()
{
var list = new LinkedList<int>();
Assert.Null(list.Head);
}
In your case, the test would have failed, and you could have backtracked the issue to your constructor.

Filter an hierarchy list and keep the path

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

Using C5 Collection Tree Data Structure

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

Breadth-first traversal

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

Categories

Resources