Introduction
After several years of just staying at the background and enjoying the fruits of other's labor, it's time to give back. I hope my first contribution will be of use.
Background
Recently, I worked on a project that requires creating a tree structure. It surprises me that until now, the .NET core library does not have a Tree data structure, and Googling on the internet, I was able to find some codes, but they were all either large or complex. So I decided to implement my own lightweight tree that has the ability to add, remove, and traverse nodes. As the tree is being traversed, you can handle each node to perform some action, similar to a SAX parser, if you are familiar with that.
Using the code
Figure 1
Figure 1 shows the class diagram of the LightTreeNode
class. Below is a sample code on how to use it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace com.delacruz.tree
{
class Program
{
static void Main(string[] args)
{
LightTreeNode root = new LightTreeNode(null);
XmlDocument doc;
LightTreeNode parent;
root.Name = "ROOT";
LightTreeNode child = new LightTreeNode(root);
child.Name = "A1";
setPayLoad(child, "Text for A1 Node", "id=1", "name=Adam");
child = new LightTreeNode(root);
child.Name = "A2";
setPayLoad(child, "A2 Node", "id=2", "name=Alice");
parent = child;
child = new LightTreeNode(parent);
child.Name = "B1";
setPayLoad(child, "B1 Node", "id=3", "name=Kathyleen");
child = new LightTreeNode(parent);
child.Name = "B2";
setPayLoad(child, "B2 Node", "id=4", "name=Eliza");
child = new LightTreeNode(parent);
child.Name = "B3";
setPayLoad(child, "B3 Node", "id=6", "name=Mark");
parent = child;
child = new LightTreeNode(parent);
child.Name = "C1";
child = new LightTreeNode(parent);
child.Name = "C2";
setPayLoad(child, "C2 Node", "id=8", "name=Kurabara");
child = new LightTreeNode(parent);
child.Name = "C3";
setPayLoad(child, "C3 Node", "id=9", "name=Yuseke");
child = new LightTreeNode(root);
child.Name = "A3";
setPayLoad(child, "Node for A3", "id=10", "name=Lovinia");
parent = child;
child = new LightTreeNode(parent);
child.Name = "B4";
setPayLoad(child, "Madel Node B4", "id=11", "name=Madel");
parent = child;
child = new LightTreeNode(parent);
child.Name = "C4";
child = new LightTreeNode(parent);
child.Name = "C5";
parent = root.getNodeByName("A3");
child = new LightTreeNode(parent);
child.Name = "B5";
child = new LightTreeNode(root);
child.Name = "A4";
setPayLoad(child, "Node for A4", "id=15", "name=Eugene");
LightTreeNode.nodeTraverse handler = onNodeTraverse;
handler(root);
root.traverse(handler, root);
doc = new XmlDocument();
root.Data = doc;
handler = onNodeTraverseForXML;
handler(root);
root.traverse(handler, root);
Console.WriteLine(((XmlElement)root.Data).OuterXml);
string filePath = string.Format("{0}/LightTreeNodeSample.xml",
Environment.GetFolderPath(Environment.SpecialFolder.Personal));
doc.Save(filePath);
Console.ReadKey();
}
public static void onNodeTraverse(LightTreeNode node)
{
for (int i = 0; i < node.getDepth(); i++)
Console.Write(" ");
Console.WriteLine(node.Name);
}
public static void onNodeTraverseForXML(LightTreeNode node)
{
XmlDocument doc;
XmlElement elem;
XmlElement parentElem;
if (node.Data != null && node.Data.GetType() == typeof(System.Xml.XmlDocument))
{
doc = (XmlDocument)node.Data;
elem = doc.CreateElement(node.Name);
doc.AppendChild(elem);
node.Data = elem;
}
else
{
parentElem = (XmlElement)node.Parent.Data;
elem = parentElem.OwnerDocument.CreateElement(node.Name);
parentElem.AppendChild(elem);
if (node.Payload != null)
{
doc = parentElem.OwnerDocument;
MyPayLoad payload = (MyPayLoad)node.Payload;
XmlText text = doc.CreateTextNode(payload.Text);
elem.AppendChild(text);
foreach (string key in payload.Attributes.Keys)
{
XmlAttribute attr = doc.CreateAttribute(key);
attr.Value = payload.Attributes[key];
elem.Attributes.Append(attr);
}
}
node.Data = elem;
}
}
private static void setPayLoad(LightTreeNode node,
string text, params string[] attrs)
{
}
#region Private class
class MyPayLoad
{
public Dictionary<string, string> Attributes =
new Dictionary<string, string>();
public string Text;
}
#endregion
}
}
...
Points of Interest
The default behavior of the traversal is LeftRight, meaning the tree will walk the node down to the last child before traversing the sibling node (next node on the same level).
Set the method to TopDown and the tree walking will be nodes on the same level first, then children of each node.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.