How to traverse a N ary tree - c#

I have some working code with the help of others which creates a 3 deep N ary tree (or just 3 linked nodes), but I don't know how to traverse the list of nodes to find data - for example the trip distance for CarNo=6, Driver=Thor4 and TripNo=38. Sorry if this is trivial, I'm new to data structures and extensive net searches hasn't helped. Thanks for any help.
public class Node
{
public List<Node> Children = new List<Node>();
public Node Parent = null;
public Node(Node fromParent = null)
{
if (fromParent != null)
{
Parent = fromParent;
fromParent.Children.Add(this);
}
}
}
public class Root : Node
{
public int PoolNo;
public int CarNo;
string Make;
public Root(int _PoolNo, int _CarNo, string _Make) : base(null)
{
PoolNo = _PoolNo;
CarNo = _CarNo;
Make = _Make;
}
}
public class Parameter : Node
{
public string Driver;
public Parameter(string _Driver, Node fromParent = null) : base(fromParent)
{
Driver = _Driver;
}
}
public class Value : Node
{
public int TripDistance;
public int TripNo;
public Value(int _TripDistance, int _TripNo, Node fromParent = null) : base(fromParent)
{
TripDistance = _TripDistance;
TripNo = _TripNo;
}
}
List<Node> CarPool = new List<Node>();
public void IDTree()
{
Random Rnd = new Random();
for (int K = 1; K <= 20; K++)
{
var Car = new Root(6,K, "Ford" + K); // PoolNo,CarNo,Make
for (int KK = 1; KK <= 30; KK++)
{
var Driver = new Parameter("Thor" + KK, Car); // Driver
for (int KKK = 1; KKK <= 58; KKK++)
{
int Distance = Rnd.Next(1, 1000);
var Details = new Value(Distance, KKK, Driver); // TripDistance,TripNo
}
}
CarPool.Add(Car);
}
// traverse CarPool list to find trip distance for Carno 6, driver Thor4, tripno 38
foreach(var T in CarPool)
{
// not sure how to do this...
}
}

Related

How to add an element at an index in singly linked list in C#

I am implementing linked-list data-structure in C#. I am facing below issue.
When I am try to add element at an index in singly linked list then it not working.
below is my code. Issue is in function AddToIndex. It is not working properly.
Node
public class DNode
{
public int data;
public DNode next;
public DNode(int d)
{
data = d;
}
}
LinkedList
public class DLinkedList
{
public int data;
public DNode Next { get; set; }
public DNode Head { get; private set; }
public DNode Tail { get; private set; }
public int Count { get; set; }
public void AddToHead(int element)
{
DNode temp = new DNode(element);
temp.next = Head;
Head = temp;
Count++;
if (Count == 1)
{
Tail = Head;
}
}
public void AddToIndex(int element, int index)
{
DNode temp = new DNode(element);
for (int i = 1; i < index - 1; i++)
{
Head = Head.next;
}
temp.next = Head;//in this case infinite link list
//temp.next = Head.next; in this case one element is removed.
Head.next = temp; // whole link list is not created, partial linked list created
}
public void Display()
{
DNode temp = Head;
while (temp != null)
{
System.Console.WriteLine(temp.data);
temp = temp.next;
}
}
}
To display result set
static class Program
{
static void Main(string[] args)
{
DLinkedList dLinked = new DLinkedList();
dLinked.AddToHead(5);
dLinked.AddToHead(7);
dLinked.AddToHead(10);
dLinked.AddToHead(11);
Console.WriteLine("---Add Head---");
dLinked.Display();
dLinked.AddToIndex(12, 4);
Console.WriteLine("---After AddToIndex function");
dLinked.Display();
}
}
Result on Console:
---Add Head---
11
10
7
5
---After AddToIndex function Called --
7
12
5
Note: I am just building this no test cases is run .
you are modifying the head of the linked list, which should not be done. try taking another temp variable and assign it to head. like the code below.
public void AddToIndex(int element, int index)
{
DNode temp = new DNode(element);
DNode temp1=Head;
for (int i = 1; i < index - 1; i++)
{
temp1 = temp1.next;
}
temp.next=temp1.next
temp1.next=temp
}

How to avoid out of memory using trie by C#

how to write billions of data into a trie with less memory
I want to extract some infomation from news like company names,so I write billions of company names into a trie,but it needs much memory and throw out of memory exception,I don't know how to solve it,so anyone can help,thanks in advance.
public class Node
{
public char Value { get; set; }
public List<Node> Children { get; set; }
public int Depth { get; set; }
public string Code { get; set; }
public bool Terminal { get; set; }
public Node(char value, int depth)
{
Value = value;
Depth = depth;
Children = new List<Node>();
}
public Node FindChildNode(char c)
{
foreach (var child in Children)
if (child.Value == c)
return child;
return null;
}
}
public class Trie
{
private Node _root;
public Trie()
{
_root = new Node('^',0);
}
public Node Prefix(string s)
{
var currentNode = _root;
var result = currentNode;
foreach (var c in s)
{
currentNode = currentNode.FindChildNode(c);
if (currentNode == null)
break;
result = currentNode;
}
return result;
}
public void Insert(string randomLength,string code)
{
var commonPrefix = Prefix(randomLength);
var current = commonPrefix;
for (var i = current.Depth; i < s.Length; i++)
{
var newNode = new Node(s[i], current.Depth + 1);
if (i+1==s.Length)
{
newNode.Terminal = true;
newNode.Code = code;
}
current.Children.Add(newNode);
current = newNode;
}
}
}
Trie t=new Trie();
t.Insert("C","ABCG00DFD");
The aboved statement run 1000000000 Loops and the "C" can be replaced with different string with different length,as the loops increasing,it throw out of memory exception,so how to avoid or change it?
Have a go at this Trie and see if you can get it to work for what you need:
public class Trie : Dictionary<char, Trie>
{
public void Add(string value)
{
var c = String.IsNullOrEmpty(value) ? '\0' : value[0];
if (!this.ContainsKey(c))
{
this[c] = new Trie();
}
if (c != '\0')
{
this[c].Add(value.Substring(1));
}
}
}

Bind a linkedlist to a datagridview

I'm trying to bind a linkedlist to a datagridview. The method below works for the properties in the class except the array.
If I declare the array as a new instance the linkedlist is created correctly, but the array is not bound into the datagridview.
If the array is created as a property (I think the code is correct) causes An unhandled exception of type 'System.StackOverflowException' occurred when the linkedlist is created.
Thanks for any help.
public class PayoffNode
{
public int DealNo { get; set; }
public string Category { get; set; }
public string Strategy { get; set; }
public string GreekType { get; set; }
// declare array as instance or as a property?
//public double[] Data = new double[22];
public double[] Data
{
get { return Data; }
set { Data = value; }
}
}
LinkedList<Globals.PayoffNode> PayLL = new LinkedList<Globals.PayoffNode>();
Random Rnd = new Random();
for (int K = 1; K <= 10; K++)
{
var T = new Globals.PayoffNode();
T.Category = "Account==" + K;
T.GreekType = "Greek==" + K;
T.DealNo = K;
T.Strategy = "Strategy==" + K;
for (int DP = 1; DP <= 21; DP++)
{
T.Data[DP] = Rnd.Next(10, 99);
}
PayLL.AddLast(T);
}
List<Globals.PayoffNode> qP = (from P in PayLL
where P.Category == "Account==4" && P.DealNo == 4 && P.GreekType == "Greek==4" && P.Strategy == "Strategy==4"
select P).ToList();
PayoffTable.DataSource = qP;
Update:
Thanks for the comments, this seems to be working.
public class PayoffNode
{
public int DealNo { get; set; }
public string Category { get; set; }
public string Strategy { get; set; }
public string GreekType { get; set; }
public double Data1 { get; set; }
public double Data2 { get; set; }
public double Data3 { get; set; }
public double[] Data = new double[22];
}
LinkedList<Globals.PayoffNode> PayLL = new LinkedList<Globals.PayoffNode>();
Random Rnd = new Random();
for (int K = 1; K <= 10; K++)
{
var T = new Globals.PayoffNode();
T.Category = "Account==" + K;
T.GreekType = "Greek==" + K;
T.DealNo = K;
T.Strategy = "Strategy==" + K;
for (int DP = 1; DP <= 21; DP++)
{
T.Data[DP] = Rnd.Next(10, 99);
}
PayLL.AddLast(T);
}
List<Globals.PayoffNode> qP = (from P in PayLL
where P.Category == "Account==4" && P.DealNo == 4 && P.GreekType == "Greek==4" && P.Strategy == "Strategy==4"
select new Globals.PayoffNode()
{
Category=P.Category,
DealNo=P.DealNo,
GreekType=P.GreekType,
Strategy=P.Strategy,
Data1=P.Data[1],
Data2 = P.Data[2],
Data3 = P.Data[3],
}).ToList();
PayoffTable.DataSource = qP;
One way to avoid making 21 Data properties is to convert the List to DataTable:
class PayoffNode
{
public int DealNo;
public string Category;
public double[] Data; // = new double[21];
}
and then
Random Rnd = new Random();
List<PayoffNode> PayLL = Enumerable.Range(1, 10).Select(i => new PayoffNode {
DealNo = i,
Category = "Account==" + i,
Data = Enumerable.Range(1, 21).Select(d => (double)Rnd.Next(10, 99)).ToArray()
}).ToList();
// List<PayoffNode> to DataTable
var dt = new DataTable();
dt.Columns.Add("DealNo", typeof(int));
dt.Columns.Add("Category"); // typeof(string) by default
for (int i = 1; i <= 21; i++)
dt.Columns.Add("Data" + i, typeof(double));
foreach (var P in PayLL)
{
var dr = dt.Rows.Add(P.DealNo, P.Category);
for (int i = 0; i < 21; i++)
dr[i+2] = P.Data[i]; // +2 is the number of fields before the Data fields
}
PayoffTable.DataSource = dt;
dt.DefaultView.RowFilter = " Category = 'Account==4' ";
The advantage is that you set the DataSource only once and just change the RowFilter to filter it. Also, any changes made in the DataGridView change the DataTable and vice-versa.
Note that arrays in C# and most other languages start from 0 and not from 1 ( .Data[0] to access the first item in the array ), so the for loop to access the Data array in my example is from 0 to 20.
public double[] Data
{
get { return Data; }
set { Data = value; }
}
This is the problem, the object in the set and get method needs to refer to a different object otherwise whenever the object value is set or trying to be retrieved it will just keep calling these methods infinitely. should be...
private double[] _data;
public double[] Data
{
get { return _data; }
set { _data = value; }
}
or...
public double[] Data { get; set; }

How to transform list of hierarchyid into a binary tree

I am working on a multi-level marketing (binary) which looks like this:
(but the binary tree is not required to be perfect. A node can have 0-2 child)
My problem is the data that I fetch from the database is flat list.
Notice that I am using hierarchyid (sql server 2014)
Basically the TextNode column is like a breadcrumb.
every slash / represents a level.
If I have TextNode of /1/ as root. then every node that starts with /1/ belongs to that root which are /1/, /1/1/ and /1/1/1/ (the root node is included which will be the level 0)
I've tried the accepted answer in this question but its not working.
How can I transform the flatlist to a Binary Tree so that I can easily traverse and display it on a screen?
Im using C#, ASP MVC 5, SQL Server 2014 if it matters.
I implement exactly this code According to Alex implementation but as is mentioned in some case it didn't work correctly .. have a look to my Image and my code (which copied from Alex post) [data in the database are correct but in tree view seems some problems ]
public class Row : IRow<string>
{
public string TextNode { get; }
public string Value { get; }
public long Id { get; }
public string FIN { get; }
public Row(string textNode, string userName, long id, string fin)
{
FIN = fin;
Id = id;
TextNode = textNode;
Value = userName;
}
}
public interface IRow<out T>
{
string TextNode { get; }
long Id { get; }
string FIN { get; }
T Value { get; }
}
public class TreeNode<T>
{
private struct NodeDescriptor
{
public int Level { get; }
public int ParentIndex { get; }
public NodeDescriptor(IRow<T> row)
{
var split = row.TextNode.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
Level = split.Length;
ParentIndex = split.Length > 1 ? int.Parse(split[split.Length - 2]) - 1 : 0;
}
}
public T title { get; }
public long Id { get; }
public string FIN { get; }
public List<TreeNode<T>> children { get; }
private TreeNode(T value, long id, string fin)
{
Id = id;
FIN = fin;
title = value;
children = new List<TreeNode<T>>();
}
public static TreeNode<T> Parse(IReadOnlyList<IRow<T>> rows)
{
if (rows.Count == 0)
return null;
var result = new TreeNode<T>(rows[0].Value, rows[0].Id, rows[0].FIN);
FillParents(new[] { result }, rows, 1, 1);
return result;
}
private static void FillParents(IList<TreeNode<T>> parents, IReadOnlyList<IRow<T>> rows, int index, int currentLevel)
{
var result = new List<TreeNode<T>>();
for (int i = index; i < rows.Count; i++)
{
var descriptor = new NodeDescriptor(rows[i]);
if (descriptor.Level != currentLevel)
{
FillParents(result, rows, i, descriptor.Level);
return;
}
var treeNode = new TreeNode<T>(rows[i].Value, rows[i].Id, rows[i].FIN);
parents[descriptor.ParentIndex].children.Add(treeNode);
result.Add(treeNode);
}
}
}
g
this is also my JSON output for more information :
{"title":"Earth","Id":32,"FIN":"FIN","children":[{"title":"Europe","Id":33,"FIN":"FIN001","children":[{"title":"France","Id":35,"FIN":"FIN001001","children":[{"title":"Paris","Id":36,"FIN":"FIN001001001","children":[]},{"title":"Brasilia","Id":41,"FIN":"FIN002001001","children":[]},{"title":"Bahia","Id":42,"FIN":"FIN002001002","children":[]}]},{"title":"Spain","Id":38,"FIN":"FIN001002","children":[{"title":"Madrid","Id":37,"FIN":"FIN001002001","children":[{"title":"Salvador","Id":43,"FIN":"FIN002001002001","children":[]}]}]},{"title":"Italy","Id":45,"FIN":"FIN001003","children":[]},{"title":"Germany","Id":48,"FIN":"FIN001004","children":[]},{"title":"test","Id":10049,"FIN":"FIN001005","children":[]}]},{"title":"South America","Id":34,"FIN":"FIN002","children":[{"title":"Brazil","Id":40,"FIN":"FIN002001","children":[{"title":"Morano","Id":47,"FIN":"FIN001003001","children":[]}]}]},{"title":"Antarctica","Id":39,"FIN":"FIN003","children":[{"title":"McMurdo Station","Id":44,"FIN":"FIN003001","children":[]}]}]}
Here is a very simple implementation (assuming that Nodes are in the right order), which may be enhanced in multiple ways
public interface IRow<out T>
{
string TextNode { get; }
T Value { get; }
}
public class TreeNode<T>
{
private struct NodeDescriptor
{
public int Level { get; }
public int ParentIndex { get; }
public NodeDescriptor(IRow<T> row)
{
var split = row.TextNode.Split(new [] {"/"}, StringSplitOptions.RemoveEmptyEntries);
Level = split.Length;
ParentIndex = split.Length > 1 ? int.Parse(split[split.Length - 2]) - 1 : 0;
}
}
public T Value { get; }
public List<TreeNode<T>> Descendants { get; }
private TreeNode(T value)
{
Value = value;
Descendants = new List<TreeNode<T>>();
}
public static TreeNode<T> Parse(IReadOnlyList<IRow<T>> rows)
{
if (rows.Count == 0)
return null;
var result = new TreeNode<T>(rows[0].Value);
FillParents(new[] {result}, rows, 1, 1);
return result;
}
private static void FillParents(IList<TreeNode<T>> parents, IReadOnlyList<IRow<T>> rows, int index, int currentLevel)
{
var result = new List<TreeNode<T>>();
for (int i = index; i < rows.Count; i++)
{
var descriptor = new NodeDescriptor(rows[i]);
if (descriptor.Level != currentLevel)
{
FillParents(result, rows, i, descriptor.Level);
return;
}
var treeNode = new TreeNode<T>(rows[i].Value);
parents[descriptor.ParentIndex].Descendants.Add(treeNode);
result.Add(treeNode);
}
}
}
Sample usage:
public class Row : IRow<string>
{
public string TextNode { get; }
public string Value { get; }
public Row(string textNode, string userName)
{
TextNode = textNode;
Value = userName;
}
}
class Program
{
static void Main(string[] args)
{
IRow<string>[] rows =
{
new Row("/", "Ahmed"),
new Row("/1/", "Saeed"),
new Row("/2/", "Amjid"),
new Row("/1/1/", "Noura"),
new Row("/2/1/", "Noura01"),
new Row("/2/2/", "Reem01"),
new Row("/1/1/1", "Under_noura")
};
var tree = TreeNode<string>.Parse(rows);
PrintTree(tree);
}
private static void PrintTree<T>(TreeNode<T> tree, int level = 0)
{
string prefix = new string('-', level*2);
Console.WriteLine("{0}{1}", prefix, tree.Value);
foreach (var node in tree.Descendants)
{
PrintTree(node, level + 1);
}
}
}

ASP.Net : DataTable convert to JSON with Hierarchy

Hi I'm having a problem in converting my dataTable to JSON format but i cannot get the output that i want.
Here is the example of the datatable
Parent Child
P1 c1
P1 c2
P1 c3
P2 c4
the output that I need is:
[{
Parent:P1,
Child:[
{c1},
{c2},
{c3}
]
},
{
Parent:P2
Child:[{c4}]
}]
But the Output that i always get is:
[{Parent:P1, Child:c1}, {Parent:P1, Child:c2}, {Parent:P1, Child:c3}, {Parent:P2,
Child:c4}]
Use this following code to get your desired result.
public class ParentNode
{
public ParentNode()
{
this.Child = new List<ChildNode>();
}
public string Parent { get; set; }
public List<ChildNode> Child { get; set; }
}
public class ChildNode
{
public string Child { get; set; }
}
class DataTableTOJSON
{
public static string GetJSON(DataTable dt)
{
List<ParentNode> parent = new List<ParentNode>();
for (int i = 0; i < dt.Rows.Count; i++)
{
var innerRow = dt.Rows[i]["Parent"];
var objParent = new ParentNode();
bool alreadyExists = parent.Any(x => x.Parent.Contains(innerRow.ToString()));
if (alreadyExists)
continue;
DataRow[] foundRows = dt.Select("[Parent]='" + innerRow + "'");
for (int k = 0; k < foundRows.Count(); k++)
{
var objChild = new ChildNode();
objChild.Child = foundRows[k]["Child"].ToString();
objParent.Child.Add(objChild);
}
objParent.Parent = innerRow.ToString();
parent.Add(objParent);
}
JavaScriptSerializer jsonString = new JavaScriptSerializer();
return jsonString.Serialize(parent);
}
}
Your will get the following output.
[{"Parent":"P1","Child":[{"Child":"c1"},{"Child":"c2"},{"Child":"c3"}]},{"Parent":"P2","Child":[{"Child":"c4"}]}]
I hope this will help you.

Categories