C# class for a graph Node - c#

I tried creating a Binary tree assuming it will have max of 2 child nodes. But for a graph it will have one or more graph nodes connected to it. How can I create a simple class for a graph node like the below which I created for a tree. The reason for suggestion is because I am trying for a simple code to find all nodes info tied to a particular node.
class TreeNode
{
public int value { get; set; }
public TreeNode leftNode { get; set; }
public TreeNode rightNode { get; set; }
}

In case of graph, any node can have arbitrary many edges (neighbor nodes), so you have to use a collection, say List<T>:
// TValue - let's generalize
// (e.g. you may want ot have double or string value associated with the node)
class GraphNode<TValue> {
private List<GraphNode<TValue>> m_Connected = new List<GraphNode<TValue>>();
public TValue value { get; set; }
// get (and no set) - we don't want to assign the collection as whole
// if we want to add/remove a neighbor we'll call Neighbors.Add, Neighbors.Remove
public List<GraphNode<TValue>> Neighbors {
get {
return m_Connected;
}
}
}

Related

C# defining Automatic Properties in Generic Class

I'm new in C# and I am completing the book "Microsoft Visual C# 2013 Step by Step" written by John Sharp.
An exercise, regarding "Generics", I found this code:
public class Tree<TItem> where TItem : IComparable<TItem>
{
public TItem NodeData { get; set; }
public Tree<TItem> LeftTree { get; set; }
public Tree<TItem> RightTree { get; set; }
public Tree(TItem nodeValue)
{
this.NodeData = nodeValue;
this.LeftTree = null;
this.RightTree = null;
}
public void Insert(TItem newItem)
{
TItem currentNodeValue = this.NodeData;
if (currentNodeValue.CompareTo(newItem) > 0)
{
// Insert the new item into the left subtree
// code here....
}
else
{
// Insert the new item into the right subtree
// code here....
}
}
}
I can't understand why he defined the properties in different mode.
One in this way:
public TItem NodeData { get; set; }
And the others in this:
public Tree<TItem> LeftTree { get; set; }
public Tree<TItem> RightTree { get; set; }
Someone can explain me why? Thank you
These properties are being used for different things. As their name suggest:
NodeData is used to facilitate the information stored in the tree.
LeftTree/RightTree are there to facilitate the topology of the tree - each current object (node) is basically a root of a tree rooted at itself. So as it is a binary tree it has two direct descendants - the left and the right nodes.
Where the part where the generics come to play is about the what is the kind of data stored in the tree. So the NodeData is trivially of "type" TItem. The left and right nodes are of type Tree<TItem> so to ensure that at any depth of the tree it is a TItem type of data that is stored.
To make it simpler lets suppose that you wanted to create a binary tree of integers. Then you'd model it by:
public class Tree
{
public int Data { get; set; }
public Tree Left {get; set; }
public Tree Right {get; set; }
}
I think this way you can really see what is the fundamental difference between the Data and Left, Right properties.
He defines a tree. The NodeData property is the current node value. Then if the value is smaller than the the current node, the new value is put on the left, otherwise on the right. If the type of LeftValue and RightValue are Tree, it's to have a parent-child structure. This class allows to create a data structure like binary tree.

C# - Traversing Nodes of a Tree and Identify level

I have an application that allows a user to select items from a tree structure that are then passed to a method that builds a report. The item is the smallest level of granularity and contains an id value. I need to produce an enumerable object that can be used to produce both summery level reports and individual item reports. For example, the picture bellow shows the tree and the desire report structure.
What I need is to be able to identify or flag items that need to be printed individually. In other words if item is not found in any child groups then mark it as needs to print individual. This is important because it is possible for the item to exist in more than one grouping. How can I parse through the tree and check if the item exists in a child node?
The Item and ItemSet(groups) classes are as follows:
public class Item
{
public int Property1 { get; set; }
public int Property2 { get; set; }
public int Property3 { get; set; }
public int Property4 { get; set; }
}
public class ItemSet
{
public List<Item> Items { get; set; }
//.
//.
//.
//.
public List<ItemSet> ItemSets { get; set; }
}
Notice that an itemset can contain other item sets. Also, the list of Items includes all items including item in children. I need a mechanism to check for if the item exists at that level alone.
UPDATE
To further clarify, I have added summarized class diagrams to illustrate the relationships/composition of Items, ItemSets, and the application as a whole.This is a legacy code base so and so i do not have much flexibility and must make do with most of what is in existence. When getAllItems() is called on a partiular set, it returns all of its decedents, even if it is an item the belongs to a nested set. I need to be able to determine if it is a direct decedent or a child of a sub set.
foreach (var item in itemSet.getAllItems())
{
if (item.Parent == itemSet)
{
// Is child of itemSet
}
else
{
// Is descendant of nested itemSet
}
}

C# Receive certain object from recursive ObservableCollection

I have an ObservableCollection<ParameterNodeEntity>.
ParameterNodeEntity is a custom class:
public class ParameterNodeEntity
{
public ParameterNodeEntity()
{
Nodes = new ObservableCollection<ParameterNodeEntity>();
Parameters = new ObservableCollection<ParameterEntity>();
}
public string Name { get; set; }
public string Path { get; set; }
public ObservableCollection<ParameterNodeEntity> Nodes { get; set; }
public ObservableCollection<ParameterEntity> Parameters { get; set; }
}
As you can see, it can contain both items from its own type (ParameterNodeEntity) and Parameters (ParameterEntity), as well as having a name and a path.
The ParameterEntity looks like this:
public abstract class ParameterEntity
{
public ParameterEntity(string name)
{
Name = name;
}
public string Name { get; set; }
public string Path { get; set; }
}
Both classes have a Path property.
As an example:
Node1
- Node2
- Node3
- Parameter1
- Parameter2
- Node4
- Node5
Node 4 would have the path Node1.Node2.Node3.Node4. Parameter1 would have the path Node1.Node2.Node3.(Parameter)Parameter1.
What I'm trying to do is to remove a specific item by its path. I tried the following:
public void DeleteParameterNode(ObservableCollection<ParameterNodeEntity> collection, string path)
{
collection.Remove(collection.SingleOrDefault(i => i.Path == path));
}
This works for the item at the highest level, but not for the others.
I appreciate any help and advice.
You don't have any code to navigate to a given node from the top level given an arbitrarily deep path. There is no way for ObservableCollection (or any other piece of code) to know what "Node1.Node2.Node3" even means.
It's no wonder it works for the top level but not the others. In your top-level collection, there is an object pathed "Node1", but the object pathed "Node1.Node2" is actually in the "Node1".Nodes collection, not the top level one.
You have to add code to parse your path and navigate the object tree (possibly recursively) in order to remove the right item from the right collection.
Unfortunately, ObservableCollection does not have any possibility to find a specific object inside a multi-level collection.
Using this approach will deliver the desired object:
private ParameterNodeEntity _searchNodeResult;
public void SearchByPath(ParameterNodeEntity nodeEntity, string path)
{
bool found = false;
if (nodeEntity.Path != path)
{
foreach (ParameterNodeEntity subNode in nodeEntity.Nodes)
{
if (!found)
{
SearchByPath(subNode, path);
}
}
}
else
{
_searchNodeResult = nodeEntity;
found = true;
}
}
SearchByPath requires two parameters: First, the top-level object and second, the parameter to find the desired object.
This is not a very beautiful approach, but in my case it works because the searched-for item definitely exists in all cases.
_searchNodeResult will hold the found object.
Have you tried this:
public void DeleteParameterNode(ObservableCollection<ParameterNodeEntity> collection, string path)
{
foreach (var item in collection.Where(i => i.Path == path))
{
collection.Remove(item);
}
}

Iteration of an object, that may have parent, or child of it's own same type

I have a class that may have a parent, or list of children of the same type of it's own. The following code snippet should explain my scenario.
public abstract class X{
public virtual List<X> ChildItems { get; set; }
public virtual X ParentItem { get; set; }
}
I would like to know if there is a particularly efficient method to traverse the objects from an object of type X, checking if the object has a parent, or children starting from bottom up.
public static void SaveSetup(X obj) {
//logic here
}
Any help is appreciated.
What you are dealing with is a tree structure (or possibly many disconnected tree structures). A tree structure has a root element. Usually, a tree structure is traversed starting from the root. If you want to start from any element in the tree, I suggest you to first get the root element and then traverse in the usual manner.
The easiest way to traverse a recursive structure is to use recursive method, i.e., a method that calls itself.
public abstract class X
{
public virtual List<X> ChildItems { get; set; }
public virtual X ParentItem { get; set; }
// Method for traversing from top to bottom
public void Traverse(Action<X> action)
{
action(this);
foreach (X item in ChildItems) {
item.Traverse(action);
}
}
// Get the root (the top) of the tree starting at any item.
public X GetRootItem()
{
X root = this;
while (root.ParentItem != null) {
root = root.ParentItem;
}
return root;
}
}
Now you can save the setup with
X root = item.GetRootItem();
root.Traverse(SaveSetup);
Example with lambda expression. Prints every item of the tree assuming that ToString() has been overridden to return a meaningful string.
root.Traverse(x => Console.WriteLine(x));
Traverse from given object to root (ParentItem = null)
public static void SaveSetup(X obj) {
while (obj != null)
{
// logic here
obj = obj.ParentItem;
}
}

How to code a truly generic tree using Generics

Lets say I have a Node class as follows:
class Node<T>
{
T data;
List<Node<T>> children;
internal Node(T data)
{
this.data = data;
}
List<Node<T>> Children
{
get
{
if (children == null)
children = new List<Node<T>>(1);
return children;
}
}
internal IEnumerable<Node<T>> GetChildren()
{
return children;
}
internal bool HasChildren
{
get
{
return children != null;
}
}
internal T Data
{
get
{
return data;
}
}
internal void AddChild(Node<T> child)
{
this.Children.Add(child);
}
internal void AddChild(T child)
{
this.Children.Add(new Node<T>(child));
}
}
The problem is that each and every node of the tree is confined to a single type. However, there are situations where the root node is of one type, which has children of another type which has children of a third type (example documents-->paragraphs-->lines-->words).
How do you define a generic tree for such cases?
If you want a strict hierarchy of types you could declare them like this:
class Node<T, TChild> {...}
Node<Document, Node<Paragraph, Node<Line, Word>>>
I did not claim it would be pretty. :)
How do you define a generic tree for such cases?
I wouldn't try to in the first place. If what I wanted to model was:
I have a list of documents
A document has a list of paragraphs
A paragraph has a list of words
then why do you need generic nodes at all? Make a class Paragraph that has a List<Word>, make a class Document that has a List<Paragraph>, and then make a List<Document> and you're done. Why do you need to artificially impose a generic tree structure? What benefit does that buy you?
Have all of your sub-objects implement a specific eg IDocumentPart then declare Node
I have been reluctant to offer the code example attached, feeling that I don't have a strong sense, yet, of the "norms" of StackOverFlow in terms of posting code that may be "speculative," and, feeling that this particular frolic is some form of "mutant species" escaped from the laboratory on "The Island of Dr. Moreau" :) And, I do think the answer by Eric Lippert above is right-on.
So please take what follows with "a grain of salt" as just an experiment in "probing" .NET inheritance (uses FrameWork 3.5 facilities). My goal in writing this (a few months ago) was to experiment with an Abstract Class foundation for Node structure that implemented an internal List<> of "itself," then implement strongly-typed classes that inherited from the Abstract class ... and, on that foundation, build a generalized Tree data structure.
In fact I was surprised when I tested this, that it worked ! :)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// experimental code : tested to a limited extent
// use only for educational purposes
namespace complexTree
{
// foundation abstract class template
public abstract class idioNode
{
// a collection of "itself" !
public List<idioNode> Nodes { private set; get; }
public idioNode Parent { get; set; }
public idioNode()
{
Nodes = new List<idioNode>();
}
public void Add(idioNode theNode)
{
Nodes.Add(theNode);
theNode.Parent = this;
}
}
// strongly typed Node of type String
public class idioString : idioNode
{
public string Value { get; set; }
public idioString(string strValue)
{
Value = strValue;
}
}
// strongly typed Node of type Int
public class idioInt : idioNode
{
public int Value { get; set; }
public idioInt(int intValue)
{
Value = intValue;
}
}
// strongly type Node of a complex type
// note : this is just a "made-up" test case
// designed to "stress" this experiment
// it certainly doesn't model any "real world"
// use case
public class idioComplex : idioNode
{
public Dictionary<idioString, idioInt> Value { get; set; }
public idioComplex(idioInt theInt, idioString theString)
{
Value = new Dictionary<idioString, idioInt>();
Value.Add(theString, theInt);
}
public void Add(idioInt theInt, idioString theString)
{
Value.Add(theString, theInt);
theInt.Parent = this;
theString.Parent = this;
}
}
// special case the Tree's root nodes
// no particular reason for doing this
public class idioTreeRootNodes : List<idioNode>
{
public new void Add(idioNode theNode)
{
base.Add(theNode);
theNode.Parent = null;
}
}
// the Tree object
public class idioTree
{
public idioTreeRootNodes Nodes { get; set; }
public idioTree()
{
Nodes = new idioTreeRootNodes();
}
}
}
So, to the test : (call this code from some EventHandler on a WinForm) :
// make a new idioTree
idioTree testIdioTree = new idioTree();
// make a new idioNode of type String
idioString testIdioString = new idioString("a string");
// add the Node to the Tree
testIdioTree.Nodes.Add(testIdioString);
// make a new idioNode of type Int
idioInt testIdioInt = new idioInt(99);
// add to Tree
testIdioTree.Nodes.Add(testIdioInt);
// make another idioNode of type String
idioString testIdioString2 = new idioString("another string");
// add the new Node to the child Node collection of the Int type Node
testIdioInt.Nodes.Add(testIdioString2);
// validate inheritance can be verified at run-time
if (testIdioInt.Nodes[0] is idioString) MessageBox.Show("it's a string, idiot");
if (!(testIdioInt.Nodes[0] is idioInt)) MessageBox.Show("it's not an int, idiot");
// make a new "complex" idioNode
// creating a Key<>Value pair of the required types of idioNodes
idioComplex complexIdio = new idioComplex(new idioInt(88), new idioString("weirder"));
// add a child Node to the complex idioNode
complexIdio.Add(new idioInt(77), new idioString("too weird"));
// make another idioNode of type Int
idioInt idioInt2 = new idioInt(33);
// add the complex idioNode to the child Node collection of the new Int type idioNode
idioInt2.Nodes.Add(complexIdio);
// add the new Int type Node to the Tree
testIdioTree.Nodes.Add(idioInt2);
// validate you can verify the type of idioComplex at run-time
MessageBox.Show(" tree/2/0 is complex = " + (testIdioTree.Nodes[2].Nodes[0] is idioComplex).ToString());
If the "smell" of this code is as bad as the fruit that here in Thailand we call the "durian" : well, so be it :) An obvious possible "weirdness" in this experiment is that you could have references to the same Node in more than one place in the tree at the same time.

Categories