Finding non-binary tree depth - c#

Can I find non-binary tree depth.
Every node can have multiple children. We don't know how much is the maximum count of nodes.
public class Node
{
private List<Node> nodes;
private string nodeName;
public Node(string nodeName)
{
nodes = new List<Node>();
this.nodeName = nodeName;
}
public List<Node> Nodes
{
get { return this.nodes; }
set { this.nodes = value; }
}
protected string NodeName
{
get { return this.nodeName; }
}
}

You can do something like this to calculate the maximum depth (including the root node):
public static int Depth(Node root, int depth)
{
int result = depth + 1;
foreach (var node in root.Nodes)
result = Math.Max(result, Depth(node, depth + 1));
return result;
}
You would call it passing in 0 for the initial depth:
int depth = Depth(root, 0);
If you just want to count ALL the nodes rather than the depth:
public static int CountExcludingRoot(Node root)
{
return root.Nodes.Sum(node => 1 + CountExcludingRoot(node));
}
(This excludes the root node, so you need to add one to the value returned to get the total of all nodes including the root).

Related

AStar Shortest Path using C#

I have been trying to write a function to find the shortest path, implementing the AStar algorithm. I have gone through many solutions on net and on this forum. But my bad, I am having a tough time understanding where exactly I need to 'remove the node from the path' if the path did not hit the destination. Infact the adding and removing nodes as we go along a path and as we come back after reaching a dead-end in the recursion, seemed a bit challenging to understand. At the end of the recursion, if the path is not found, I am clearing the path and returning it, which I know is not the way to implement. However, I am sharing the code here. Could someone kindly help me understand what I am doing wrong?
Here is the Node class;
public class Node
{
public string Name { get; private set; }
public Coordinate Location { get; private set; }
public double g { get; set; }
public double h { get; set; }
public double cost { get { return this.g + this.h; } }
public List<Node> Neighbours { get; set; }
public Node(string name, Coordinate location)
{
Name = name;
Location = location;
Neighbours= new List<Node>();
}
public void AddNeighbours(List<Node> neighbours)
{
Neighbours.AddRange(neighbours);
}
public double distanceTo(Node node)
{
return Location.Distance(node.Location);
}
}
...and here is the Graph class.
public class Graph
{
List<Node> Nodes = new List<Node>();
public Graph(List<Node> nodes)
{
Nodes = nodes;
}
public List<Node> GetShortestPath(Node source, Node destination, HashSet<Node> visited = null, List<Node> path = null )
{
if ( visited == null ) { visited = new HashSet<Node>(); } // Initialize the visited nodes list
if(path == null ) { path = new List<Node>() {}; } // initialize the shortest path list
if (source == destination){ path.Add(destination); return path;}
visited.Add(source); // Currently visiting this node. So, add to the visited nodes
path.Add(source); // Add the current source to the path
foreach (Node neighbour in source.Neighbours) // for each neighbour node
{
// Update the g and h distances
neighbour.g = source.g + source.distanceTo(neighbour);
neighbour.h = neighbour.distanceTo(destination);
}
// Collect the non-visited neighbours
List<Node> nonVisitedNeighbours = source.Neighbours.Where(n => !visited.Contains(n)).ToList();
if (nonVisitedNeighbours.Count > 0) // if non-visited neighbours not empty
{
// sort the neighbours in ascending order and take the first one.
// that will be the closest neighbour with the lowest cost
Node nextNeighbour = nonVisitedNeighbours.OrderBy(n => n.cost).ToList().First();
return GetShortestPath(nextNeighbour, destination, visited, path);
}
path.Clear(); // I hope this is not the right way, but somewhere path.Remove(source) to be added. But not clear where...
Console.WriteLine("No path found!");
return path; // This should return an empty list
}
}
Ok... I fixed it. Here is the final implementation...
public List<Node> GetPath(
Node startNode,
Node targetNode
)
{
List<Node> openSet = new List<Node>();
HashSet<Node> closedSet = new HashSet<Node>();
openSet.Add(startNode);
while (openSet.Count > 0)
{
Node currentNode = openSet[0];
List<Node> nodesWithLesserCost = openSet
.Skip(1)
.ToList()
.Where(node => node.Cost < currentNode.Cost || node.Cost == currentNode.Cost && node.H < currentNode.H)
.OrderBy(n => n.Cost)
.ToList();
if (nodesWithLesserCost.Any())
{
currentNode = nodesWithLesserCost.First();
}
openSet.Remove(currentNode);
closedSet.Add(currentNode);
if (currentNode == targetNode)
{
return RetracePath(startNode, targetNode);
}
foreach (Node neighbour in currentNode.Neighbours)
{
if (closedSet.Contains(neighbour))
{
continue;
}
double newMovementCostToNeighbour = currentNode.G + currentNode.DistanceTo(neighbour);
if(newMovementCostToNeighbour < neighbour.G || !openSet.Contains(neighbour))
{
neighbour.G = newMovementCostToNeighbour;
neighbour.H = neighbour.DistanceTo(targetNode);
neighbour.Parent = currentNode;
if (!openSet.Contains(neighbour))
{
openSet.Add(neighbour);
}
}
}
}
Console.WriteLine("No Path Found...!");
return new List<Node>();
}

I'm struggling to get a foreach loop working to loop through each element of a LinkedList

Im trying to do a Depth first traversal on graph node but I cant get my for each loop to loop correctly
Here is the code for doing the search
The foreach line is the problem
public void DepthFirstTraverse(T startID, ref List<T> visited)
{
LinkedList<T> adj;
Stack<T> toVisit = new Stack<T>();
GraphNode<T> current = new GraphNode<T>(startID);
toVisit.Push(startID);
while (toVisit.Count != 0)
{
current.ID = toVisit.Peek();
toVisit.Pop();
visited.Add(current.ID);
Console.WriteLine(current.GetAdjList());
foreach(T n in current.GetAdjList())
{
Console.WriteLine("Loop working");
if(toVisit.Contains(n)==false && visited.Contains(n)==true)
{
toVisit.Push(n);
}
}
}
}
Here is the graphnode code, it calls the getadjlist and should loop through for each element in that list, currently it doesnt loop at all
public class GraphNode
{
private T id; // data stored in the node (“id” of the node).
private LinkedList adjList; // adjacent list of the node
// constructor
public GraphNode(T id)
{
this.id = id;
adjList = new LinkedList<T>();
}
// set and get the data stored in the node
public T ID
{
set { id = value; }
get { return id; }
}
//add a directed edge from “this” node to the node "to”
public void AddEdge(GraphNode<T> to)
{
adjList.AddFirst(to.ID);
}
// returns the adjacent list of the node
public LinkedList<T> GetAdjList()
{
return adjList;
}
}

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

Creating a Treeview recursively

I want to create a treeview in c# which will group file by prefix (here the prefix is a marked by the separator _). The following files should give this tree:
Files list :
p_a
p_a_test
p_LIG
p_p
p_p_c
p_p_c2
p_p_ccc
p_p_test
p_tres
TestLineGraph1
TestLineGrpah
Corresponding tree:
|--p_
|--p_a
|--p_a_test
|--p_LIG
|--p_p
|--p_p_
|--p_p_c
|--p_p_c2
|--p_p_ccc
|--p_p_test
|--p_tres
TestLineGraph1
TestLineGrpah
Here's my attempt of code:
private GraphUINode(List<string> subNodes, GraphUINode parent, string name, int lvl = 0)
: base(parent.m_viewDataSubControl)
{
parent.Nodes.Add(this);
this.Name = name;
this.Text = name;
string currentPrefix = "";
int pertinentSubNodes = 0;
while (pertinentSubNodes < subNodes.Count -1 && subNodes[pertinentSubNodes].Split('_').Length < 2+ lvl)
pertinentSubNodes++;
for (int i = 0; i <= lvl; i++)
{
currentPrefix += subNodes[pertinentSubNodes].Split('_')[i] + "_";
}
List<String> children = new List<string>();
foreach (string child in subNodes)
{
// The child is in the same group than the previous one
if (child.StartsWith(currentPrefix))
{
children.Add(child);
}
else
{
// Create a node only if needed
if (children.Count > 1)
{
// Create the new node
new GraphUINode(children, this, currentPrefix, lvl + 1);
children.Clear();
children.Add(child);
}
else
{
new GraphTemplateNode(this, m_viewDataSubControl, child);
}
currentPrefix = "";
for (int i = 0; i <= lvl; i++)
{
currentPrefix += child.Split('_')[i] + "_";
}
}
}
}
But I miss a few ones in the final result:
How can I get its back? Even when I debug step by step I can't find the logical way to do it.
So the first thing that we'll want to do here is take our strings and turn them into a tree. Once we have a tree then mapping those nodes to a TreeView is quite easy.
We'll start out with the definition for the tree itself:
public class Node<T>
{
public Node(T value, IEnumerable<Node<T>> children)
{
Value = value;
Children = children;
}
public T Value { get; private set; }
public IEnumerable<Node<T>> Children { get; private set; }
}
Nice and easy, each node is just a value and a collection of children.
Next we'll write a method to take a sequence of sequences, and build a tree from it. The idea here is that we'll group all of the items based on the first value in their sequence, build a node for each group, and then recursively call the method on the group to get the children for that node.
public static IList<Node<T>> GroupToTree<T>(this IEnumerable<IEnumerable<T>> source)
{
return GroupToTree(source.Select(sequence => sequence.GetEnumerator()));
}
private static IList<Node<T>> GroupToTree<T>(IEnumerable<IEnumerator<T>> source)
{
return source.WhereHasNext()
.GroupBy(iterator => iterator.Current)
.Select(group => new Node<T>(group.Key, GroupToTree(group)))
.ToList();
}
//This ensures that the iterators all get disposed
private static IEnumerable<IEnumerator<T>> WhereHasNext<T>(
this IEnumerable<IEnumerator<T>> source)
{
foreach (var iterator in source)
{
if (iterator.MoveNext())
yield return iterator;
else
iterator.Dispose();
}
}
Now we can take the raw data, split each of the strings into sequences of strings, and then map each of the nodes that we have here into UI-based nodes for presentation:
List<string> rawData = new List<string>();
//TODO populate raw data
Func<Node<string>, TreeNode> selector = null;
selector = node => new TreeNode(node.Value, node.Children.Select(selector).ToArray());
var nodes = rawData.Select(line => line.Split('_').AsEnumerable())
.GroupToTree()
.Select(selector);

How to select certain child node in TreeView, C#

I am having a problem with selecting a certain child node.
What I want to achieve: I you have this treeview for example (one parent with two child nodes): Parent -Child with a value 5 -Child with a value 2.
I want to add these two values and assign them to Parent node: Parent result 7 -Child 5 -Child 2.
Of course, a bigger treeview would have several parents and lots of children and they will all add up to one root node.
How can I do this?? pls help.
thx, Caslav
You could do something like the following. It assumes the value you want is part of the text (the last value after the last space).
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace TreeViewRecurse
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
RecurseTreeViewAndSumValues(treeView1.Nodes);
}
public void RecurseTreeViewAndSumValues(TreeNodeCollection treeNodeCol)
{
int tree_node_sum = 0;
foreach (TreeNode tree_node in treeNodeCol)
{
if (tree_node.Nodes.Count > 0)
{
RecurseTreeViewAndSumValues(tree_node.Nodes);
}
string[] node_split = tree_node.Text.Split(' ');
string num = node_split[node_split.Length - 1];
int parse_res = 0;
bool able_to_parse = int.TryParse(num, out parse_res);
if (able_to_parse)
{
tree_node_sum += parse_res;
}
}
if (treeNodeCol[0].Parent != null)
{
string[] node_split_parent = treeNodeCol[0].Parent.Text.Split(' ');
node_split_parent[node_split_parent.Length - 1] = tree_node_sum.ToString();
treeNodeCol[0].Parent.Text = string.Join(" ", node_split_parent);
}
}
}
}
private TreeNode SearchTree(TreeNodeCollection nodes, string searchtext)
{
TreeNode n_found_node = null;
bool b_node_found = false;
foreach (TreeNode node in nodes)
{
if (node.Tag.ToString() as string == searchtext)
{
b_node_found = true;
n_found_node = node;
}
if (!b_node_found)
{
n_found_node = SearchTree(node.Nodes, searchtext);
}
}
return n_found_node;
}
Source:
http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_21895513.html
I used a modified version of Redburn's answer to find a treenode by name:
private TreeNode GetNodeByName(TreeNodeCollection nodes, string searchtext)
{
TreeNode n_found_node = null;
bool b_node_found = false;
foreach (TreeNode node in nodes)
{
//show(node.Name + ":" +searchtext);
if (node.Name == searchtext)
{
//show("score!");
b_node_found = true;
n_found_node = node;
return n_found_node;
}
if (!b_node_found)
{
//show("here");
n_found_node = f_get_node_by_name(node.Nodes, searchtext);
if (n_found_node!=null)
{
return n_found_node;
}
}
}
return null;
}
Dunno if this matches your request, but this will add all childs > parent node
private void button2_Click(object sender, EventArgs e)
{
int grandTotal = CalculateNodes(this.treeView1.Nodes);
}
private int CalculateNodes(TreeNodeCollection nodes)
{
int grandTotal = 0;
foreach (TreeNode node in nodes)
{
if (node.Nodes.Count > 0)
{
int childTotal = CalculateNodes(node.Nodes);
node.Text = childTotal.ToString();
grandTotal += childTotal;
}
else
{
grandTotal += Convert.ToInt32(node.Text);
}
}
return grandTotal;
}
you should do some error checking etc etc to make it solid
You could inherit from TreeNode with something like this:
public class TreeNodeEx : TreeNode {
// only displayed when having no children
public int Value { get; set; }
public bool HasChildren {
get { return Nodes.Count > 0; }
}
public int GetSumOfChildren() {
if (!HasChildren)
return Value;
var children = Nodes.Cast<TreeNode>().OfType<TreeNodeEx>();
int sum = 0;
foreach (var child in children)
sum += child.GetSumOfChildren();
return sum;
}
}
Like this:
public class TotalingTreeNode : TreeNode
{
private int _value = 0;
public int Value
{
get
{
if (this.Nodes.Count > 1)
return GetTotaledValue();
else
return _value;
}
set
{
if (this.Nodes.Count < 1)
_value = value;
}
}
private int GetTotaledValue()
{
foreach (TotalingTreeNode t in this.Nodes.Cast<TotalingTreeNode>())
{
_value += t.Value;
}
return _value;
}
}
In WinForms a childnode of a tree knows its Parent. So you can reach the parent at any time using the TreeNode.Parent property. Vice versa every Node knows it's child nodes. You can reach them using Node.Nodes. This collection has an indexer that allows you to access the child nodes using an int or a string.
To find a TreeNode with a special Key use the following code:
treeView.Nodes.Find("nodeKey", true);
You can finde a description of this method at MSDN

Categories