Height of binary search tree iteratively - c#

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.

Related

Determine if a tree is balanced or not in linear time

The following programme returns whether a tree is balanced or not. A tree is said to be balanced if a path from the root to any leaf has the same length.
using System;
namespace BalancedTree
{
public class MainClass
{
static bool isBalanced(int[][] sons)
{
return isBalanced(sons, 0);
}
static bool isBalanced(int[][] sons, int startNode)
{
int[] children = sons[startNode];
int minHeight = int.MaxValue;
int maxHeight = int.MinValue;
bool allChildBalanced = true;
if(children.Length == 0)
return true;
else
{
foreach (int node in children)
{
int h = height(sons, node);
if(h > maxHeight)
maxHeight = h;
if(h < minHeight)
minHeight = h;
}
}
foreach (int node in children)
{
allChildBalanced = allChildBalanced && isBalanced(sons, node);
if(!allChildBalanced)
return false;
}
return Math.Abs(maxHeight - minHeight) < 2 && allChildBalanced;
}
static int height(int[][] sons, int startNode)
{
int maxHeight = 0;
foreach (int child in sons[startNode])
{
int thisHeight = height(sons, child);
if(thisHeight > maxHeight)
maxHeight = thisHeight;
}
return 1 + maxHeight;
}
public static void Main (string[] args)
{
int[][] sons = new int[6][];
sons[0] = new int[] { 1, 2, 4 };
sons[1] = new int[] { };
sons[2] = new int[] { 3, 5};
sons[3] = new int[] { };
sons[4] = new int[] { };
sons[5] = new int[] { };
Console.WriteLine (isBalanced(sons));
}
}
}
My problem is that my code is very inefficient, due to recursive calls to function
static int height(int[][] sons, int startNode)
making the time complexity exponential.
I know this can be optimised in case of a binary tree, but I'm looking for a way to optimise my programme in case of a general tree as described above.
One idea would be for instance to call function 'height' from the current node instead of startNode.
My only constraint is time complexity which must be linear, but I can use additional memory.
Sorry, but I have never done C#. So, there will be no example code.
However, it shouldn't be too hard for you to do it.
Defining isBalanced() recursively will never give best performance. The reason is simple: A tree can still be unbalanced, if all sub-trees are balanced. So, you can't just traverse the tree once.
However, your height() function already does the right thing. It visits every node in the tree only once to find the height (i.e. maximum length from the root to a leaf).
All you have to do is write a minDistance() function that finds the minimum length from the root to a leaf. You can do this using almost the same code.
With these functions a tree is balanced if and only if height(...)==minDistance(...).
Finally, you can merge both function into one that returns a (min,max) pair. This will not change time complexity but could bring down execution time a bit, if returning pairs is not too expensive in C#

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;

trouble with adding child node 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);
}
}

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.

Duplicate a linked list

I wrote a method which creates a copy of linked list.
Can you guys think of any method better than this?
public static Node Duplicate(Node n)
{
Stack<Node> s = new Stack<Node>();
while (n != null)
{
Node n2 = new Node();
n2.Data = n.Data;
s.Push(n2);
n = n.Next;
}
Node temp = null;
while (s.Count > 0)
{
Node n3 = s.Pop();
n3.Next = temp;
temp = n3;
}
return temp;
}
You can do it in one pass, something like this:
public static Node Duplicate(Node n)
{
// handle the degenerate case of an empty list
if (n == null) {
return null;
}
// create the head node, keeping it for later return
Node first = new Node();
first.Data = n.Data;
// the 'temp' pointer points to the current "last" node in the new list
Node temp = first;
n = n.Next;
while (n != null)
{
Node n2 = new Node();
n2.Data = n.Data;
// modify the Next pointer of the last node to point to the new last node
temp.Next = n2;
temp = n2;
n = n.Next;
}
return first;
}
#Greg, I took your code and made it even a bit shorter :)
public static Node Duplicate(Node n)
{
// Handle the degenerate case of an empty list
if (n == null) return null;
// Create the head node, keeping it for later return
Node first = new Node();
Node current = first;
do
{
// Copy the data of the Node
current.Data = n.Data;
current = (current.Next = new Node());
n = n.Next;
} while (n != null)
return first;
}
The Do-While construct is often forgotten, but fits well here.
A Node.Clone() method would be nice as well.
+1 to Greg for the nice example.
Recursive method for small/medium lists.
public static Node Duplicate(Node n)
{
if (n == null)
return null;
return new Node() {
Data = n.Data,
Next = Duplicate(n.Next)
};
}
I'm sorry if I've missed something, but what's wrong with
LinkedList<MyType> clone = new LinkedList<MyType>(originalLinkedList);
.NET API on LinkedList Constructors
EDIT: Just wanted to emphasize an extremely good point made in the comment below:
"...changing non-value objects on the duplicate changes them on the
original too. Meaning you might want to be sure you don't need a deep
copy before trying anything on this page."

Categories

Resources