I have one List type of my own struct.This is my struct.
public struct outlineData
{
public string paragraphID;
public string outlineText;
public int outlineLevel;
}
and my List is
List<outlineData> outlinePara = new List<outlineData>();
So, i have added so many outlineData in my outlinePara List.Now, i want to create a TreeView based on the outlineData's outlineLevel.
for example : outlineData's outlineLevel may be 0,1,2,3,1,2....0,1...0,1,1,1,1,1,2,3,2....
So, Now i want to create a Treeview like that...
0
1
2
3
1
2
0
1
0
1
1
1
1
1
2
3
2
TreeNode childNode;
if (outlineParaInfo.outlineLevel == 0)
{
headNode = new TreeNode(outlineParaInfo.outlineText);
TreeView11.Nodes.Add(headNode);
}
else if (outlineParaInfo.outlineLevel == 1)
{
childNode = new TreeNode(outlineParaInfo.outlineText);
headNode.ChildNodes.Add(childNode);
}
Please guide me to get a correct logic for this problem...
[EDITED TO USE System.Web.UI.WebControls.TreeView PER OP COMMENT]
How about something like the following pseudo code:
int currentLevel = 0;
TreeNode currentNode = null;
TreeNode childNode = null;
foreach(var outLineItem in outlinePara)
{
if(outLineItem.outlineLevel == 0)
{
currentNode = new TreeNode(
outLineItem.paragraphID, outLineItem.outlineText);
yourTreeView.Nodes.Add(currentNode);
continue;
}
if(outLineItem.outlineLevel > currentLevel)
{
childNode = new TreeNode(
outLineItem.paragraphID, outLineItem.outlineText);
currentNode.ChildNodes.Add(childNode);
currentNode = childNode;
currentLevel = outLineItem.outlineLevel;
continue;
}
if(outLineItem.outlineLevel < currentLevel)
{
currentNode = currentNode.Parent;
childNode = new TreeNode(
outLineItem.paragraphID, outLineItem.outlineText);
currentNode.ChildNodes.Add(childNode);
currentLevel = outLineItem.outlineLevel;
}
}
Like Antonio Bakula said, use parentParagraphID.
You can populate a treeview dynamically by using a recursive function
Change your outlineLevel with parentParagraphID.
public struct outlineData
{
public string paragraphID;
public string outlineText;
//public int outlineLevel;
public string parentParagraphID;
}
After creating your list.
List<outlineData> outlinePara = new List<outlineData>();
First insert the root TreeNode, then insert the rest.
TreeNode rNode = new rNode();
rNode.Name = "root";
outlinePara.Add(rNode);
...
outlinePara.Add(lastNode);
After inserting all the nodes, just launch this function.
populate(rNode, rNode.Name);
This function will create your level structure for your TreeView.
public void populate(TreeNode node, string parentParID)
{
var newList = this.outlinePara.Where(x => x.parentParagraphID == parentParID).toList();
foreach(var x in newList)
{
TreeNode child = new TreeNode();
child.Name = paragraphID;
child.Text = outlineText;
populate(child, child.Name);
node.Nodes.Add(child);
}
}
You will get a TreeView like this
root
|-->0
| |-->1
| |-->1
| |-->2
| |-->2
| |-->2
|
|-->0
| |-->1
| ...
...
Tip
In this code the ID is a string, it's much better to use something else, and it has to be unique, so you won't get a problem with your data placed in another parentNode.
private void generateTreeView()
{
int currentLevel = 0;
TreeNode currentNode = null;
TreeNode childNode = null;
foreach (var outLineItem in outlineParagraph)
{
if (outLineItem.outlineLevel == 0)
{
currentNode = new TreeNode(outLineItem.outlineText);
TreeView11.Nodes.Add(currentNode);
currentLevel = outLineItem.outlineLevel;
continue;
}
if (outLineItem.outlineLevel > currentLevel)
{
childNode = new TreeNode(outLineItem.outlineText);
currentNode.ChildNodes.Add(childNode);
currentNode = childNode;
currentLevel = outLineItem.outlineLevel;
continue;
}
if (outLineItem.outlineLevel < currentLevel)
{
//logic to find exact outlineLevel parent...
currentNode = findOutlineLevelParent(outLineItem.outlineLevel, currentNode);
if(currentNode!=null)
currentNode = currentNode.Parent;
childNode = new TreeNode(outLineItem.outlineText);
currentNode.ChildNodes.Add(childNode);
currentLevel = outLineItem.outlineLevel;
currentNode = childNode;
continue;
}
if (outLineItem.outlineLevel == currentLevel)
{
currentNode = currentNode.Parent;
childNode = new TreeNode(outLineItem.outlineText);
currentNode.ChildNodes.Add(childNode);
currentLevel = outLineItem.outlineLevel;
currentNode = childNode;
continue;
}
}
}//generateTreeView Ends here...
private TreeNode findOutlineLevelParent(int targetLevel, TreeNode currentNode)
{
while (currentNode.Parent != null)
{
currentNode = currentNode.Parent;
if (currentNode.Depth == targetLevel)
{
return currentNode;
}
}
return null;
} //findOutlineLevelParent ends here...
Related
I'm working on SPOJ problem where you have to write an algorithm that based on input string conditions outputs new string, but you can't exceede time limit.
problem link
The fastest i could get was by using two stacks, but time limit was still exceeded, now I tried implementing doubly linked list, but it's twice slower than when I used stack. Do you have any idea on how can I increase performance of implemented linked list, or maybe should I use other data structure for this problem? Thought of implementing Node as a structure but not really sure if you can do that.
using System;
namespace spoj
{
class LinkedList
{
private Node head;
private Node tail;
private int length;
public Node Head { get => head; }
public Node Tail { get => tail; }
public int Length { get => length; }
public LinkedList(Node head = null, Node tail = null, int length = 0)
{
this.head = head;
this.tail = tail;
this.length = length;
}
public void AddFirst(char value)
{
var addFirst = new Node(value);
addFirst.Next = head;
addFirst.Previous = null;
if (head != null)
head.Previous = addFirst;
head = addFirst;
length++;
}
public void Remove(Node node)
{
if (node.Previous == null)
{
head = node.Next;
head.Previous = null;
length--;
}
else if (node.Next == null)
{
tail = node.Previous;
tail.Next = null;
length--;
}
else
{
Node temp1 = node.Previous;
Node temp2 = node.Next;
temp1.Next = temp2;
temp2.Previous = temp1;
length--;
}
}
public void AddAfter(Node node, char input)
{
var newNode = new Node(input);
if (node.Next == null)
{
node.Next = newNode;
newNode.Previous = node;
length++;
}
else
{
Node temp1 = node;
Node temp2 = node.Next;
temp1.Next = newNode;
newNode.Previous = temp1;
newNode.Next = temp2;
temp2.Previous = newNode;
length++;
}
}
public string Print()
{
string temp = "";
if (head == null)
return temp;
for (int i = 0; i < length; i++)
{
temp += head.Value;
head = head.Next;
}
return temp;
}
}
class Node
{
private char value;
private Node next;
private Node previous;
public char Value { get => value; }
public Node Next { get => next; set { next = value; } }
public Node Previous { get => previous; set { previous = value; } }
public Node(char value)
{
this.value = value;
next = null;
previous = null;
}
}
class Program
{
static void Main(string[] args)
{
int testNum = Int32.Parse(Console.ReadLine());
for (int i = 0; i < testNum; i++)
{
var list = new LinkedList();
string input = Console.ReadLine();
var node = list.Head;
for (int j = 0; j < input.Length; j++)
{
if ((input[j] == '<' && node == null) | (input[j] == '>' && (node == null || node.Next == null)) | (input[j] == '-' && (node == null || node.Previous == null)))
continue;
else if (input[j] == '<')
{
node = node.Previous;
}
else if (input[j] == '>')
{
node = node.Next;
}
else if (input[j] == '-')
{
node = node.Previous;
list.Remove(node.Next);
}
else
{
if (node == null)
{
list.AddFirst(input[j]);
node = list.Head;
continue;
}
list.AddAfter(node, input[j]);
node = node.Next;
}
}
Console.WriteLine(list.Print());
}
}
}
}
An implementation using a linked list will not be as fast as one that uses StringBuilder, but assuming you are asking about a linked list based implementation I would suggest not to reimplement LinkedList. Just use the native one.
This means you don't have to change much in your code, just this:
Define the type of the list nodes as char: new LinkedList<char>();
Instead of .Head use .First
Instead of .Print use string.Join("", list)
However, there are these problems in your code:
When the input is >, you should allow the logic to execute when node is null. Currently you continue, but a null may mean that your "cursor" is in front of the non-empty list, so you should still deal with it, and move the "cursor" to list.First
When the input is -, you should still perform the removal even when node.Previous is null, because it is not the previous node that gets removed, but the current node. We should imagine the cursor to be between two consecutive nodes, and your removal logic shows that you took as rule that the cursor is between the current node and node.Next. You could also have taken another approach (with the cursor is just before node), but important is that all your logic is consistent with this choice.
When executing the logic for - -- in line with the previous point -- you should take into account that node.Previous could be null, and in that case you cannot do the removal as you have it. Instead, you could first assign the node reference to a temporary variable, then move the cursor, and then delete the node that is referenced by the temporary reference.
Here is the corrected code, using the native LinkedList implementation. I moved the logic for doing nothing (your continue) inside each separate case, as I find that easier to understand/debug:
using System;
using System.Collections.Generic;
public class Test
{
public static void Main()
{
int testNum = Int32.Parse(Console.ReadLine());
for (int i = 0; i < testNum; i++)
{
var list = new LinkedList<char>();
string input = Console.ReadLine();
var node = list.First;
for (int j = 0; j < input.Length; j++)
{
if (input[j] == '<')
{
if (node != null)
node = node.Previous;
}
else if (input[j] == '>')
{
if (node == null || node.Next != null)
node = node == null ? list.First : node.Next;
}
else if (input[j] == '-')
{
if (node != null) {
var temp = node;
node = node.Previous;
list.Remove(temp);
}
}
else
{
node = node == null ? list.AddFirst(input[j])
: list.AddAfter(node, input[j]);
}
}
Console.WriteLine(string.Join("", list));
}
}
}
EDIT:
Right thanks for helping earlier, I have been using and the step into and step over and it looks to be working but the nodes are not being deleted and I'm not sure why.
I actually use 5 arguments for the BST but just using the one for testing purposes. It compares and finds if it has any children no problem. Just wont set it to null.
only testing nodes with 0 or 1 children.
main
Tree aTree = new Tree();
aTree.InsertNode("a");
aTree.InsertNode("s");
aTree.InsertNode("3");
aTree.InsertNode("1");
aTree.InsertNode("p");
aTree.PreorderTraversal();
aTree.RemoveNode("p");
aTree.RemoveNode("3");
aTree.PreorderTraversal();
Console.ReadKey();
My Delete Methods are:
Tree Node
public void Remove(TreeNode root, TreeNode Delete) {
if (Data == null) {
}
if (Delete.Data.CompareTo(root.Data) < 0) {
root.nodeLeft.Remove(root.nodeLeft, Delete);
}
if (Delete.Data.CompareTo(root.Data) > 0) {
root.nodeRight.Remove(root.nodeRight, Delete);
}
if (Delete.Data == root.Data) {
//No child nodes
if (root.nodeLeft == null && root.nodeRight == null) {
root = null;
}
else if (root.nodeLeft == null)
{
TreeNode temp = root;
root = root.nodeRight;
root.nodeRight = null;
temp = null;
}
//No right child
else if (root.nodeRight == null)
{
TreeNode temp = root;
root = root.nodeLeft;
root.nodeLeft = null;
temp = null;
}
//Has both child nodes
else
{
TreeNode min = minvalue(root.nodeRight);
root.Data = min.Data;
root.nodeRight.Remove(root.nodeRight, min);
}
}
}
Find Min
public TreeNode minvalue(TreeNode node)
{
TreeNode current = node;
/* loop down to find the leftmost leaf */
while (current.nodeLeft != null)
{
current = current.nodeLeft;
}
return current;
}
Tree
public void RemoveNode(string Nation)
{
TreeNode Delete = new TreeNode(Nation);
root.Remove(root, Delete);
}
Remove is of return type void, but you're trying to assign it to root.nodeLeft and root.nodeRight, causing your type conversion error.
In general your Remove function needs to return the root of the sub-tree as the result, as in
public void Remove(TreeNode root, TreeNode Delete) {
if (Data == null) {
return null;
}
if (Delete.Data.CompareTo(root.Data) < 0) {
root.nodeLeft = (root.nodeLeft.Remove(root.nodeLeft, Delete));
return root;
}
... and so on.
Otherwise, since your nodes don't refer to their parents, there would be no way for the parent to know that the child node is gone, or that a new node is now at the root of the sub-tree.
I have null reference exception unhandled error in my red black tree code. I'm trying to remove it but I couldn't. The error is on this line
if (currentNode.left.color == Color.Red && currentNode.right.color == Color.Red)
Please can you people fix this error
Here is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Algo_Project
{
class Program
{
public enum Color
{
Red = 0, Black = 1
}
public enum direction
{
Left, Right
}
public class Node
{
public IComparable data;
public Node left;
public Node right;
public Color color = Color.Black;
public Node(IComparable data): this(data, null, null)
{
}
public Node(IComparable data, Node left, Node right)
{
this.data = data;
this.left = left;
this.right = right;
}
}
public class Tree
{
protected Node root;
protected Node freshNode;
protected Node currentNode;
protected Tree()
{
freshNode = new Node(null);
freshNode.left = freshNode.right = freshNode;
root = new Node(null);
}
protected int Compare(IComparable item, Node node)
{
if (node != root)
return item.CompareTo(node.data);
else
return 1;
}
public IComparable Search(IComparable data)
{
freshNode.data = data;
currentNode = root.right;
while (true)
{
if (Compare(data, currentNode) < 0)
currentNode = currentNode.left;
else if (Compare(data, currentNode) > 0)
currentNode = currentNode.right;
else if (currentNode != freshNode)
return currentNode.data;
else
return null;
}
}
protected void Display(Node temp)
{
if (temp != freshNode)
{
Display(temp.left);
Console.WriteLine(temp.data);
Display(temp.right);
}
}
protected void Display()
{
this.Display(root.right);
}
}
public sealed class RedBlackTree : Tree
{
private Color Black = Color.Black;
private Color Red = Color.Red;
private Node parentNode;
private Node grandParentNode;
private Node tempNode;
public void Insert(IComparable item)
{
currentNode = parentNode = grandParentNode = root;
freshNode.data = item;
int returnValue = 0;
while (Compare(item, currentNode) != 0)
{
tempNode = grandParentNode;
grandParentNode = parentNode;
parentNode = currentNode;
returnValue = Compare(item, currentNode);
if (returnValue < 0)
currentNode = currentNode.left;
else
currentNode = currentNode.right;
if (currentNode.left.color == Color.Red && currentNode.right.color == Color.Red)
{
ReArrange(item);
}
}
if (currentNode == freshNode)
{
currentNode = new Node(item, freshNode, freshNode);
if (Compare(item, parentNode) < 0)
parentNode.left = currentNode;
else
parentNode.right = currentNode;
ReArrange(item);
}
}
private void ReArrange(IComparable item)
{
currentNode.color = Red;
currentNode.left.color = Color.Black;
currentNode.right.color = Color.Black;
if (parentNode.color == Color.Red)
{
grandParentNode.color = Color.Red;
bool compareWithGrandParenrNode = (Compare(item, grandParentNode) < 0);
bool compareWithParentNode = (Compare(item, parentNode) < 0);
if (compareWithGrandParenrNode != compareWithParentNode)
parentNode = Rotate(item, grandParentNode);
currentNode = Rotate(item, tempNode);
currentNode.color = Black;
}
root.right.color = Color.Black;
}
private Node Rotate(IComparable item, Node parentNode)
{
int value;
if (Compare(item, parentNode) < 0)
{
value = Compare(item, parentNode.left);
if (value < 0)
parentNode.left = this.Rotate(parentNode.left, direction.Left);
else
parentNode.left = this.Rotate(parentNode.left, direction.Right);
return parentNode.left;
}
else
{
value = Compare(item, parentNode.right);
if (value < 0)
parentNode.right = this.Rotate(parentNode.right, direction.Right);
else
parentNode.right = this.Rotate(parentNode.right, direction.Right);
return parentNode.right;
}
}
private Node Rotate(Node node, direction direction)
{
Node tempNode;
if (direction == direction.Left)
{
tempNode = node.left;
node.left = tempNode.right;
tempNode.right = node;
return tempNode;
}
else
{
tempNode = node.right;
node.right = tempNode.left;
tempNode.left = node;
return tempNode;
}
}
}
static void Main(string[] args)
{
RedBlackTree redBlackTree = new RedBlackTree();
Random random = new Random();
for (int i = 0; i < 100000; i++)
{
redBlackTree.Insert(random.Next(1, 100000));
random.Next();
}
redBlackTree.Insert(1000001);
DateTime startTime = DateTime.Now;
int p = (int)redBlackTree.Search(1000001);
DateTime endTime = DateTime.Now;
TimeSpan TimeElapsed = (TimeSpan)(endTime - startTime);
Console.WriteLine("The number " + p + "has been found in" + TimeElapsed.Milliseconds.ToString() + "milliseconds.");
Console.ReadLine();
Console.ReadLine();
}
}
}
Please can you tell something about this error I want it fixed up till thursday 6th June 2013
When your Insert method hits a leaf, currentNode.left or currentNode.right will be null. At this point, you're not checking for null, so you'll receive this exception on that line as you try to access the color.
You need to add null checks on insert to handle the leaf condition.
hi how i can set a image for my treeView nodes... I have a parent and a child node.
here is my code:
private void btnShowLicstate_Click(object sender, EventArgs e)
{
treeLic.Nodes.Clear();
string command = "\"C:\\lmxendutil.exe\" -licstatxml -host lwserv005 -port 6200";
string output = ExecuteCommand(command);
string final_output = output.Substring(90, output.Length - 90);
XmlReader xr = XmlReader.Create(new StringReader(final_output));
var xDoc = XDocument.Load(xr);
TreeNode root = new TreeNode();
LoadTree(xDoc.Root.Element("LICENSE_PATH"), root);
treeLic.Nodes.Add(root);
treeLic.ImageList = imageList1;
}
public void LoadTree(XElement root, TreeNode rootNode)
{
foreach (var e in root.Elements().Where(e => e.Attribute("NAME") != null))
{
var node = new TreeNode(e.Attribute("NAME").Value);
rootNode.Nodes.Add(node);
if (e.Name == "FEATURE")
{
node.SelectedImageIndex = 1;
}
else if (e.Name == "USER")
{
node.SelectedImageIndex = 0;
}
LoadTree(e, node);
}
}
my problem is that i have everyone the same picture but i want for FEATURE the index 1 and for USER the Index 2 but why it don't work ? :(
You should use ImageIndex property instead of SelectedImageIndex.
The first one is the index from ImageList for node in unselected state and the second one is applied when you select node using mouse, keyboard or through code.
I have a problem that I cannot seem to solve.
I am building a TreeView dynamically and I have an ordered list. I want the TreeView to build in such a way:
Node1
_Node2
__ Node3
__ _Node..N
My code is as follows:
TreeNode tn = new TreeNode();
for (int i = 0; i < EmployeesReportingLine.Count; i++ )
{
Employee ep = EmployeesReportingLine[i];
while (tn.ChildNodes.Count > 0)
tn = tn.ChildNodes[0];
TreeNode temp = new TreeNode(ep.FullName);
if (i > 0)
tn.ChildNodes.Add(temp);
else
tn = temp;
}
TreeView1.Nodes.Add(tn);
I have made several other attempts at using recursive functions but the snippet above was my best attempt.
Thanks in advance.
private void addNode(TreeNodeCollection nodes, TreeNode newnode) {
if (nodes.Count == 0) nodes.Add(newnode);
else addNode(nodes[0].Nodes, newnode);
}
Or:
private void addNode2(TreeNode start, TreeNode newnode) {
if (start.Nodes.Count == 0) start.Nodes.Add(newnode);
else addNode2(start.Nodes[0], newnode);
}