trouble with adding child node C# - c#

I am adding a child node to the current parent node in treeview. But my problem is that it adds the new node to the end of the current parent rather than to add in the position which the if is true.
Here is my code:
for (int i = 0; i < num; i++)
{
if (action_type1 != action_type2)
{
TreeNode new_node = = treeView1.Nodes[0].Nodes[position];
string new_name = "";
new_node.Nodes.Add(new_name);
}
}
of course num, position, action_type1, and action_type2 are variables in my code and for any for loop they are different integers an strings. action_type1 is the name of nodes of treeView and action_type2 is a fixed string. if loop looks for whole the tree if there is nodes equal with the given string then leave the node otherwise insert an empty node in the tree and then do recursively.
but to make it simple, let we have:
int num = 2;
int position = 4;
string action_type1;
string action_type2;

This is what you want?
for (int i = 0; i < num; i++)
{
if (action_type1 != action_type2)
{
treeView1.Nodes[i].Nodes.Insert(position - 1, virtual_name);
}
}

Related

C# Tabbed Text File to Tree

I have text file a tabbed list that need to turned into a tree.
File content:
root
node1
node2
node2_1
node3
node3_1
node3_2
node3_2_1
node4
Tree should look like:
root
/ | \ \
node1 node2 node3 node4
| / \
node2_1 node3_1 node3_2
\
node3_2_1
I am trying to create a recursive method to create the tree but not sure how to keep track of parent and and root.
Assuming your Node class looks like this:
public class Node
{
public Node(string value)
{
Value = value;
Children = new List<Node>();
}
public string Value { get; }
public List<Node> Children{ get; }
}
You can try this method to get the tree (assuming your input is as you posted and the root is the first line):
public Node GetTree(string filePath)
{
string[] lines = System.IO.File.ReadAllLines(filePath);
//if lines is empty the tree is null
if(lines.Length == 0)
{
return null;
}
//create the root
Node root = new Node(lines[0].Trim());
//get the root leading white spaces length
int rootWhiteSpaceLength = lines[0].TakeWhile(c => c=" ").Count();
//Crete a list to hold the nodes and their white space length
List<Tuple<Node, int>> nodesAndLengths = new List<Tuple<Node, int>>();
//add the root to nodes list with it's white space length
nodesAndLengths.Add(new Tuple<Node, int>(root, rootWhiteSpaceLength));
//iterate over the lines strating from index 1
for (var i = 1; i < lines.Length, i++)
{
//create the node
Node node = new Node(lines[i].Trim());
//get the node leading white spaces length
int nodeWhiteSpaceLength = lines[i].TakeWhile(c => c=" ").Count();
//Check that is not another root
if(nodeWhiteSpaceLength <= rootWhiteSpaceLength)
{
throw new Exception("There is more than one root");
}
//find the node parent in the nodes list using LINQ
Node parent = nodesAndLengths.Last(nodeAndLength => nodeAndLength.Item2 < nodeWhiteSpaceLength).Item1;
//Alternatively using while loop
//int j = i - 1;
//while(nodeWhiteSpaceLength >= nodesAndLengths[j].Item2)
//{
//j--;
//}
//Node parent=nodesAndLengths[j].Item1;
//add the node to it's parent
parent.Children.Add(node);
//add the node to nodes list with it's white space length
nodesAndLengths.Add(New Tuple<Node, int>(node, nodeWhiteSpaceLength));
}
return root;
}

How to change this function to the recursive function

I have the following code that compares the node.Texto each both given node sets and then return one if they are equal otherwise zero. But my problem is that it just compare the first children because of nodes2.Nodes[ii] hence I know that it will not go forward more.
As I know if it was TreeNodeCollection it was easy to do recursive for each node and sub-node using foreach loop.
But here how I could change the code to the recursive version?
thanks in advance!
public int Compare_ChildNodes(TreeNode nodes1, TreeNode nodes2)
{
int length_children1 = nodes1.Nodes.Count;
int length_children2 = nodes2.Nodes.Count;
int result_int = 1;
if (length_children1 != length_children2)
{
result_int = 0;
}
else
{
for (int ii = 0; ii < length_children1; ii++)
{
if (nodes1.Nodes[ii].Text.Equals(nodes2.Nodes[ii].Text))
{
int ret = Compare_ChildNodes(nodes1.Nodes[ii], nodes2.Nodes[ii]);
result_int = ret;
}
else
{
result_int = 0;
}
}
}
return result_int;
}
I can't see any problems here. Calling Compare_ChildNodes with nodes1.Nodes[ii] and nodes2.Nodes[ii] does exactly the recursion you want.
I'd just suggest a little optimization ("early out") for your code:
public int Compare_ChildNodes(TreeNode nodes1, TreeNode nodes2)
{
int length_children1 = nodes1.Nodes.Count;
int length_children2 = nodes2.Nodes.Count;
int result_int = 1;
if (!nodes1.Text.Equals(nodes2.Text)) return 0; // not equal
if (length_children1 != length_children2) return 0; // not equal
return nodes1.Nodes.OfType<TreeNode>.Select((node, idx) =>
Compare_ChildNodes(node, nodes2.Nodes[idx]).Any(result => result == 0) ? 0 : 1;
}
I changed the comparison for the node's text to another recursion level so you can recurse using linq.
The linq Any method checks if any of the comparisons (in the Select method) returns 0 indicating that a child node collection is not equal.
The Select is called for each TreeNode in node1.Nodes and with it's index in that collection. So you can use this index to get the matching node from node2.Nodes and call Compare_ChildNodes for these two.
As soon as you find unequal (child-)nodes, you can return 0 and don't need to continue comparing the other nodes.
If you cannot use the linq statements (for Framework reasons or others), you can still use your for loop:
for (int idx = 0; idx < length_children1; idx++)
if (Compare_ChildNodes(nodes1.Nodes[idx], nodes2.Nodes[idx]) == 0)
return 0;
return 1;

How to get to next list in the List<List<Node>> when particular condition is satisfied

I have a List<Node> nodes and each node in nodes have a variable called Interest associated with it.
public static List<Node> nodes = new List<Node>();
for (int i = 0; i < Program.n; i++)
{
//int densityrandom = generateRandom();
Node n = new Node(Interest3);
Program.nodes.Add(n);
}
While class Node is as Follows:
public class Node
{
public int Density { get; set; }
public InterestProfile P1 { get; set; }
public List<Edge> adjnodes { get; set; }
public Node(InterestProfile a)
{
adjnodes = new List<Edge>();
P1 = a;
}
}
For some object Interest1 of type InterestProfile there is an array associated with it like
Interest1 = new InterestProfile(array1);
So, if you do something like nodes[0].P1.InterestArray[0], it will give me first element in the array1.
Now here is my actual question:
I am splitting up the list nodes according to user input into list of list of Node. Thus, if nodes have 100 elements in it, it will be split up into 10 lists and all those lists will stored in one list.
This is something I have in mind:
List<List<Node>> smallList = new List<List<Node>>();
for (int i = 0; i < nodes.Count; i++)
{
for(int k=0; k < smallList.Count; k++)
{
if (list[i].P1.InterestArray[0] > 5 && smallList[k].Count != 10)
{
smallList[0].Add(list[i]);
}
else smallList[k+1].Add(list[i]);
}
and so on by checking for all 5 elements in an array associated with particular node. However, when smallList[0] reaches limit of 10, I want to start adding elements from nodes in some other smallList[i]. When all the values of particular InterestArray[j] are checked for all nodes in nodes, then only it should move to checking InterestArray[j+1]. How can I program this in c#? Is my implementation correct and if yes can it be improved?
I know question is quite confusing. Please ask me if anything is difficult to understand. Any help will be highly appreciated.
Instead of creating the List<List<Node>> data structure why not simply query your existing List<Node> for the nodes you want when you need them?
e.g.
Old School:
var interestingNodes = new List<Node>();
foreach(Node node in nodes)
{
foreach(int i in note.InterestArray)
{
if(i > 5)
interestingNodes.Add(node);
}
}
Using List<T>.FindAll():
var interstingNodes = nodes.FindAll(node => node.P1.InterestArray.Contains(5));
Or in LINQ:
var interstingNodes = from node in nodes
where node.P1.InterestArray.Contains(5)
select node;

Why is my time complexity of inserting in skip list linear?

I have implemented skip list for integers. When testing method insert, I insert natural numbers from 1 to 1000000 in a for loop with counter j. I am using stopwatch also.
Appendix: in the real program, values are doubles, because I use sentinels with values
double.PositiveInfinity in double.NegativeInfinity. (but that shouldn't be the problem)
Pseudocode:
MyList = new SkipList();
stopwatch.start();
t1 = stopwatch.Elapsed.TotalMilliseconds;
for(int j = 0; j<1000000; j++){
steps = MyList.insert(j);
if(j%500==0){
t2= stopwatch.Elapsed.TotalMilliseconds -t1;
write j,t2 in a file1;
write j,steps in a file2;
t1 = t2;
}
}
When I make a graph time/number of nodes, it is linear, but graph steps/nodes is logarithmic as expected. (steps is number of loop-cycles (~operations) in the method insert).
Method insert creates extra nodes and set some poiters. Nodes are implemented in the following way:
class Node
{
public Node right;//his right neighbour - maybe "null"
public Node down;//his bottom neighbour -maybe null
public int? value;//value
public int depth;//level where node is present: 0, 1, 2 ...
public Node(int i,Node rightt,Node downn,int depthh) {
//constructor for node with two neighbours.
value = i;
right = rightt;
down = downn;
depth = depthh;
}
//there are some other contructors (for null Node etc.)
}
class SkipList
{
public Node end;//upper right node
public Node start;//upper left node
public int depth;//depth of SkipList
//there are left (-inf) and right sentinels (inf) in the SkipList.
}
Skip list is made of nodes.
Insert is defined in the class SkipList and works in the following way:
public int Insert(int value2, int depth2)
{
//returns number of steps
//depth2 is calculated like (int)(-Math.Log(0<=random double<1 ,2))
//and works as expected - probability P(depth = k) = Math.Pow(0.5,k)
//lsit of nodes, which will get a new right neighbour
List<Node> list = new List<Node>();
Node nod = start;
int steps = 0;
while (true) {
if (nod.right.value >= value2)
{
//must be added to our list
lsit.Add(nod);
if (nod.down != null)
nod = nod.down;
else
break;
}
else {
nod = nod.right;
}
steps++;
}
//depth (of skipList) is maybe < depth2, so we must create
//k = 2*(depth2-depth) new edge nodes and fix right pointers of left sentinels
List<Node> newnodes = new List<Node>();
for (int jj = 0; jj < depth2 - depth;jj++ )
{
steps++;
//new sentinels
Node end2 = new Node(double.PositiveInfinity, end,depth+jj+1);
Node start2 = new Vozlisce(double.NegativeInfinity, end2,
start,depth+jj+1);
start = start2;
end = end2;
newnodes.Add(start2);
}
//fix right pointers of nodes in the List list (from the beginning)
Node x = new Node(value,list[list.Count-1].right,0);
list[list.Count-1].right=x;
int j =1;
while(j<=Math.Min(depth2,depth)){
steps++;
//create new nodes with value value
x = new Node(value,lsit[list.Count -(j+1)].right,x,j);
list[list.Count-(j+1)].right = x;
j++;
}
//if there are some new edge sentinels, we must fix their right neighbours
// add the last depth2-depth nodes
for(int tj=0;tj<depth2-depth;tj++){
steps++;
x = new Node(value,newnodes[tj].right,x,depth+tj+1);
newnodes[tj].right = x;
}
depth = Math.Max(depth, depth2);
return steps;
}
I've implemented also a version of skip list where nodes are blocks and have n = node.depth
right neighbours, stored in array, but the graph time/num. of nodes is still linear (and steps/num. of nodes is logarithmic).
^ is "xor";
10 : 1010
6 : 0110
---------
^ : 1100 = 12
If you loop from 0 to 11, then yes - it'll appear pretty linear - you won't notice any degradation over that size. You probably want Math.Pow rather than ^, but it would be simpler to hard-code 1000000.

Height of binary search tree iteratively

I was trying out an iterative method to find the height/depth of a binary search tree.
Basically, I tried using Breadth First Search to calculate the depth, by using a Queue to store the tree nodes and using just an integer to hold the current depth of the tree. Each node in the tree is queued, and it is checked for child nodes. If child nodes are present, then the depth variable is incremented. Here is the code:
public void calcDepthIterative() {
Queue<TreeNode> nodeQ = new LinkedList<TreeNode>();
TreeNode node = root;
int level = 0;
boolean flag = false;
nodeQ.add(node);
while(!nodeQ.isEmpty()) {
node = nodeQ.remove();
flag = false;
if(node.leftChild != null) {
nodeQ.add(node.leftChild);
flag = true;
}
if(node.rightChild != null) {
nodeQ.add(node.rightChild);
flag = true;
}
if(flag) level++;
}
System.out.println(level);
}
However, the code doesn't work for all cases. For example, for the following tree:
10
/ \
4 18
\ / \
5 17 19
It shows the depth as 3, instead of 2.
I did an alternate version of it using an additional Queue to store the current depths, using the idea in this page. I wanted to avoid using an additional queue so I tried to optimize it. Here is the code which works, albeit using an additional Queue.
public void calcDepthIterativeQueue() {
Queue<TreeNode> nodeQ = new LinkedList<TreeNode>();
Queue<Integer> lenQ = new LinkedList<Integer>();
TreeNode node = root;
nodeQ.add(node);
lenQ.add(0);
int maxLen = 0;
while(!nodeQ.isEmpty()) {
TreeNode curr = nodeQ.remove();
int currLen = lenQ.remove();
if(curr.leftChild != null) {
nodeQ.add(curr.leftChild);
lenQ.add(currLen + 1);
}
if(curr.rightChild != null) {
nodeQ.add(curr.rightChild);
lenQ.add(currLen + 1);
}
maxLen = currLen > maxLen ? currLen : maxLen;
}
System.out.println(maxLen);
}
QUESTION:
Is there a way to fix the first method such that it returns the right depth?
EDIT
SEE ACCEPTED ANSWER BELOW
Java code for rici's answer:
public void calcDepthIterative() {
Queue<TreeNode> nodeQ = new LinkedList<TreeNode>();
int depth = 0;
nodeQ.add(root);
while(!nodeQ.isEmpty()) {
int nodeCount = nodeQ.size();
if(nodeCount == 0)
break;
depth++;
while(nodeCount > 0) {
TreeNode topNode = nodeQ.remove();
if(topNode.leftChild != null)
nodeQ.add(topNode.leftChild);
if(topNode.rightChild != null)
nodeQ.add(topNode.rightChild);
nodeCount--;
}
}
System.out.println(depth);
}
Here's one way of doing it:
Create a Queue, and push the root onto it.
Let Depth = 0
Loop:
Let NodeCount = size(Queue)
If NodeCount is 0:
return Depth.
Increment Depth.
While NodeCount > 0:
Remove the node at the front of the queue.
Push its children, if any, on the back of the queue
Decrement NodeCount.
How it works
Every time NodeCount is set, the scan is just about to start a new row. NodeCount is set to the number of Nodes in that row. When all of those Nodes have been removed (i.e., NodeCount is decremented to zero), then the row has been completed and all the children of nodes on that row have been added to the queue, so the queue once again has a complete row, and NodeCount is again set to the number of Nodes in that row.
public int height(Node root){
int ht =0;
if(root==null) return ht;
Queue<Node> q = new ArrayDeque<Node>();
q.addLast(root);
while(true){
int nodeCount = q.size();
if(nodeCount==0) return ht;
ht++;
while(nodeCount>0){
Node node = q.pop();
if(node.left!=null) q.addLast(node.left);
if(node.right!=null) q.addLast(node.right);
nodeCount--;
}
}
How about recurtion,
int Depth(Node node)
{
int depthR=0,depthL=0;
if(Right!=null)depthR=Depth(Right);
if(Left!=null)depthL=Depth(Left);
return Max(depthR,depthL)+1;
}
If tou want a zero based depth, just subtract the resulting depth by 1.

Categories

Resources