I am trying to find the closest common manager from a tree, given two nodes n1 and n2. This is not a binary tree. I am showing a binary tree for simplicity.
See attached image:
If I pass H & I as two nodes, it should return E
If I pass D & I as two nodes, it should return B
Look at the code, everything seems to be working fine except for case where when I pass "I" & "L" as two nodes, instead of getting E, I am getting "I" as the manager.
How can I fix it? here is a fiddle: https://dotnetfiddle.net/qOYsDO
class Node
{
public string Name { get; set; }
public List<Node> Children { get; set; }
public Node(string name)
{
Name = name;
Children = new List<Node>();
}
}
class CommonManager
{
public static Dictionary<string, Node> dictionary;
public CommonManager()
{
dictionary = new Dictionary<string, Node>();
Node root = new Node("A");
root.Children.Add(new Node("B"));
//root.Children.Add(new Node("C"));
//root.Children.Add(new Node("AA"));
root.Children[0].Children.Add(new Node("D"));
root.Children[0].Children.Add(new Node("E"));
//root.Children[1].Children.Add(new Node("F"));
//root.Children[1].Children.Add(new Node("G"));
root.Children[0].Children[1].Children.Add(new Node("H"));
root.Children[0].Children[1].Children.Add(new Node("I"));
//root.Children[1].Children[0].Children.Add(new Node("J"));
//root.Children[1].Children[0].Children.Add(new Node("K"));
root.Children[0].Children[1].Children[1].Children.Add(new Node("L"));
Node n1 = root.Children[0].Children[1].Children[1].Children[0];//L
Node n2 = root.Children[0].Children[1].Children[1];//I
Node lcm = FindLCM(root, n1, n2);
if (lcm != null)
Console.WriteLine("The LCM is " + lcm.Name);
else
Console.WriteLine("No LCM found.");
Console.ReadKey();
}
static Node FindLCM(Node root, Node n1, Node n2)
{
if (root == null)
return null;
//If selected node is n1 or n2 return node.
if (root == n1 || root == n2)
return root;
Node lcm = null;
int count = 0;
//Use debug > Windows > Parallel Watch to track variables.
foreach (Node child in root.Children)
{
Console.WriteLine(child.Name);
Node temp = FindLCM(child, n1, n2);
if (temp != null)
{
lcm = temp;
Console.WriteLine("temp.Name:--> " + temp.Name);
count++;
}
}
if (count == 2)
return root;
else
return lcm;
}
}
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));
}
}
}
I'm taking lines (I:3, I:6, D:5, etc) from a text file and splitting them on the colon. Then, taking the number after the colon and pushing it to a node in a linked list. Depending on the line, it will insert(I) or delete(D) the node. However, I'm having trouble deleting a node. I created a method called deleteNode()
I reference this method in my if statement to check whether or not the command in the file starts with I or D to be told whether it gets inserted or deleted or not. I'm having trouble on how to reference the node to be deleted in llist.deletenode();
public class LinkedList
{
Node head; // the head of list
public class Node
{
public int data;
public Node next;
// constructor
public Node(int d)
{
data = d;
next = null;
} // end of constructor
}
public void printList()
{
// traversing list and printing the contents starting from head(1)
Node n = head;
int count = 0;
while (n != null)
{
count++;
Console.Write("Node" + count + ":" + " " + n.data + " ");
n = n.next;
}
}
public void push(int new_data)
{
// ads node to list
Node new_node = new Node(new_data); //allocate new node, put in data
new_node.next = head; //make next of new node as head
head = new_node; //moving head to point to the new node
}
public static void deleteNode(Node node, Node n)
{
// deletes node from list
// find the previous node
Node prev = node;
while (prev.next != null && prev.next != n)
{
prev = prev.next;
}
// Check if node really exists in Linked List
if (prev.next == null)
{
Console.WriteLine("Given node is not" +
"present in Linked List");
return;
}
// Remove node from Linked List
prev.next = prev.next.next;
// Free memory
GC.Collect();
return;
}
}
// main method to create a linked list with 3 nodes
public static void Main(String[] args)
{
// starting with an empty list
LinkedList llist = new LinkedList();
string[] lines = File.ReadAllLines(#"C:\\Users\project\text.txt");
foreach (string line in lines)
{
// splitting the lines on the colon
string[] bits = line.Split(':');
// taking the bit after the colon and parsing
// into an integer - the i is already parsed
int x = int.Parse(bits[1]); //the value after colon
if (bits[0] == "i")
{
llist.push(x);
}
else if (bits[0] == "d")
{
deleteNode(llist, existingNode); //error here
}
}
llist.printList();
}
I think the logic should probably match that of the push method (not sure why push isn't called Add or Insert instead, though...), in that it should look for the first node whose data matches the data we want to delete.
If we start at the head, we first want to determine if the head should be deleted. If so, then we reset the head to head.next and we're done!
Otherwise, we examine head.Next to see if it's the one to delete. If it is, then we set head.Next equal to head.Next.Next, effectively removing head.Next from our list (no node is pointing to it anymore).
If head.Next is not the node to delete, then we move to the next node and continue the process.
Here's an example:
public void DeleteNode(int nodeData)
{
// First check if the head is the node to delete
if (head != null && head.data == nodeData)
{
// If it is, set the head to the next node (effectively removing it from the list)
head = head.next;
return;
}
// Start at the head node
var current = head;
while (current != null)
{
// Get the next node
var next = current.next;
// See if the next node is the one to delte
if (next != null && next.data == nodeData)
{
// It is, so set the current node's Next pointer to the *next* node's
// Next pointer (effectively removing the Next node from the list)
current.next = next.next;
return;
}
// Update our current node to the next one and keep looking
current = next;
}
}
There are a lot of issues with your code ranging from aesthetic (name casing), to syntax errors, to design errors (static functions instead of methods).
I am offering some cleanup and an example below. The result is
Print List:
Node1: 0 Node2: 1 Node3: 2 Node4: 3 Node5: 4 Node6: 5
Deleting 4
Print List:
Node1: 0 Node2: 1 Node3: 2 Node4: 3 Node5: 5
and the sample code. The main addition is a separate function that finds the previous node FindPrevious() and use the existing Head of the list in DeleteNode().
Also changed fields into properties and PascalCasing as recommended per C# design rules.
namespace ConsoleApp1
{
public class Node
{
public int Data { get; set; }
public Node Next { get; set; }
// constructor
public Node(int data)
: this(null, data)
{ }
// always add a full constructor
public Node(Node next, int data)
{
this.Data = data;
this.Next = next;
}
}
public class LinkedList
{
public Node Head { get; set; }
public string PrintList()
{
// traversing list and printing the contents starting from head(1)
Node n = Head;
int count = 0;
StringBuilder sb = new StringBuilder();
while (n != null)
{
count++;
sb.Append("Node" + count + ":" + " " + n.Data + " ");
n = n.Next;
}
return sb.ToString();
}
// adds node to list
public void Push(int data)
{
//allocate new node, put in data
//and make next of new node as head
//moving head to point to the new node
Head = new Node(Head, data);
}
public Node FindPrevious(Node node)
{
Node n = Head;
while (n!=null)
{
if (n.Next == node)
{
return n;
}
n = n.Next;
}
return null;
}
public void DeleteNode(Node node)
{
if (node==null)
{
return;
}
Node prev = FindPrevious(node);
if (prev!=null)
{
// skip over node
prev.Next = node.Next;
}
}
}
static class Program
{
static void Main(string[] args)
{
LinkedList llist = new LinkedList();
llist.Push(5);
llist.Push(4);
llist.Push(3);
llist.Push(2);
llist.Push(1);
llist.Push(0);
Console.WriteLine($"Print List:");
Console.WriteLine(llist.PrintList());
Console.WriteLine();
var existingNode = llist.Head.Next.Next.Next.Next;
Console.WriteLine($"Deleting {existingNode.Data}");
llist.DeleteNode(existingNode);
Console.WriteLine($"Print List:");
Console.WriteLine(llist.PrintList());
}
}
}
DeleteNode method takes in two arguments. You are using deleteNode as an extension method but it's a simple method with two inputs.
deleteNode(llist, nodeYouWantToDelete);
Also, your loop that checks for D isn't right
if (bits[0] == "i") { //loop that checks if command starts with i (for inserting)
llist.push(x);
} else if(bits[0] == "d") { // CHECK bits[0] not [1]
// Get the node that matches value
// check here if the node already exists then delete
deleteNode(llist, existingNode);
}
update
public void push(int new_data) { //ads node to list
Node new_node = new Node(new_data); //allocate new node, put in data
new_node.next = null; //next should always be null.
// start from head and find the node whose next = null, point that to new_node
}
public void deleteNode(Node nodeToDelete) { //deletes node from list
// start from head and keep going next until node.next = nodeToDelete
// set node.next = node.next.next;
}
Working Solution for you
public class LinkedList
{
Node head;
Node last;
public class Node
{
public int data;
public Node next;
public Node(int d)
{
data = d;
next = null;
} // end of constructor
}
public void print()
{
// traversing list and printing the contents starting from head(1)
Node n = head;
int count = 0;
while (n != null)
{
Console.Write("Node" + count++ + ":" + " " + n.data + " ");
n = n.next;
}
}
public void push(int new_data)
{
Node thisNode = new Node(new_data);
if (head == null)
{
head = thisNode;
last = head;
return;
}
last.next = thisNode;
last = last.next;
}
public void delete(Node node)
{
if (head.data == node.data)
head = head.next;
else
{
Node iterate = head;
bool deleted = false;
while (iterate.next != null)
{
if (iterate.next.data == node.data && !deleted)
{
iterate.next = iterate.next.next;
deleted = true;
continue;
}
iterate.next = iterate.next.next;
}
last = iterate;
if (!deleted)
{
Console.WriteLine("Given node is not " +
"present in Linked List");
}
// Free memory
GC.Collect();
return;
}
}
}
//and use it in the main like,
public static void Main(string[] args)
{
LinkedList llist = new LinkedList();
string[] lines = new[] { "i:1", "i:3", "d:3", "i:2", "i:1", "d:3" };
foreach(string line in lines)
{
string[] split = line.Split(':');
if (split[0] == "i") // INSERTS At the end of the list.
llist.push(int.Parse(split[1]));
else if (split[0] == "d") // Deletes the "FIRST" occurence of said number
llist.delete(new LinkedList.Node(int.Parse(split[1])));
}
Console.Read();
}
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'm trying to write a function in C# that allows me to swap two nodes of a binary tree but it does not work as expected.
Here is the class with the swap method:
class Node
{
public int value;
public Node parent { get; set; }
public Node left { get; set; }
public Node right { get; set; }
public Node addLeft(int value)
{
this.left = new Node(value);
this.left.parent = this;
this.left.left = null;
this.left.right = null;
return this.left;
}
public Node addRight(int value)
{
this.right = new Node(value);
this.right.parent = this;
this.right.left = null;
this.right.right = null;
return this.right;
}
public Node(int value)
{
this.value = value;
this.parent = null;
this.left = null;
this.right = null;
}
public Node getRoot()
{
Node n = this;
while(n.parent!=null)
{
n = n.parent;
}
return n;
}
public static void swap(ref Node n1,ref Node n2)
{
//updating references of n1 and n2 parents
if(n1.Equals(n1.parent.left)) //n1 is a left child
{
n1.parent.left = n2;
}
else if(n1.Equals(n1.parent.right)) //n1 is a right child
{
n1.parent.right = n2;
}
else
{
throw new Exception("Something is wrong");
}
if (n2.Equals(n2.parent.left)) //n2 is a left child
{
n2.parent.left = n1;
}
else if (n2.Equals(n2.parent.right)) //n2 is a right child
{
n2.parent.right = n1;
}
else
{
throw new Exception("Something is wrong");
}
//updating references of n1 and n2 childs
if(n1.left != null)
{
n1.left.parent = n2;
}
if (n1.right != null)
{
n1.right.parent = n2;
}
if (n2.left != null)
{
n2.left.parent = n1;
}
if (n2.right != null)
{
n2.right.parent = n1;
}
//Swapping n1 and n2 references
Node t_p = n1.parent;
Node t_l = n1.left;
Node t_r = n1.right;
n1.parent = n2.parent;
n1.left = n2.left;
n1.right = n2.right;
n2.parent = t_p;
n2.left = t_l;
n2.right = t_r;
}
}
And here is my main function:
static void Main(string[] args)
{
Node root = new Node(10);
Node a = root.addLeft(1);
Node b = root.addRight(2);
Node c = a.addLeft(3);
Node d = a.addRight(4);
Node e = b.addLeft(5);
Node f = b.addRight(6);
Node g = d.addLeft(7);
Node h = d.addRight(8);
Node.swap(ref a,ref d);
Console.WriteLine("Value is: " + root.left.value);
Console.WriteLine("Value is: " + root.left.right.value);
Console.WriteLine("Root: " + a.getRoot().value);
Console.WriteLine("Root: " + d.getRoot().value);
Console.Read();
}
The output of the code above is:
Value is: 4
Value is: 1
It hangs after the second Console.WriteLine and I don't understand why. Can you please tell me what am I doing wrong?
EDIT:
And if I try to swap the nodes multiple times, the "Something is wrong" exception is thrown.
while (n.parent != null)
This condition is never met so you're stuck in a while loop.
Your swap method creates a node with an infinite ancestor tree (parent). If you walk up the current node n in .getRoot() you never find a null parent.
Here is the state of the tree before we begin swapping
((Root(10))
/ \
a(1) b(2)
/ \ / \
c(3) d(4) e(5) f(6)
/ \
g(7) h(8)
If you swap only the child nodes for a & d, you end up with an circular reference for parent.
Something more like this for your swap method should work. I left this verbose for clarity's sake.
public static void swap(ref Node A, ref Node B)
{
var newA = new Node(B.value);
var newB = new Node(A.value);
newA.left = A.left;
newA.right = A.right;
newA.parent = A.parent;
newB.left = B.left;
newB.right = B.right;
newB.parent = B.parent;
// Fix up parent node for A
if (A.parent.left == A)
{
// A is a left node
A.parent.left = newA;
}
if (A.parent.right == A)
{
// A is a Right node
A.parent.right = newA;
}
// Fix up parent node for B
if (B.parent.left == B)
{
// B is a left node
B.parent.left = newB;
}
if (B.parent.right == B)
{
// B is a right node
B.parent.right = newB;
}
if (newA.right == B)
{
// If B was a right child of A, update reference to newB
newA.right = newB;
}
if (newA.left == A)
{
// If B was a left child of A, update reference to newB
newA.left = newB;
}
if (newB.right == A)
{
// If A was a right child of B, update reference to newA
newB.right = newA;
}
if (newB.left == A)
{
// If A was a left child of B, update reference to newA
newA.left = newB;
}
// Update child references to be orphaned to point to new parents for A
A.left.parent = newA;
A.right.parent = newA;
// Update child references to be orphaned to point to new parents for A
B.left.parent = newB;
B.right.parent = newB;
// Final Swap to update ref types
A = newA;
B = newB;
}
Desired State after the swap
((Root(10))
/ \
d(4) b(2)
/ \ / \
c(3) a(1) e(5) f(6)
/ \
g(7) h(8)
Here is some quick & dirty verification code that runs in the console. I haven't checked all possible cases, but it seems to update all the relevant nodes in this case now.
static void Main(string[] args)
{
var root = new Node(10);
var a = root.addLeft(1);
var b = root.addRight(2);
var c = a.addLeft(3);
var d = a.addRight(4);
var e = b.addLeft(5);
var f = b.addRight(6);
var g = d.addLeft(7);
var h = d.addRight(8);
Node.swap(ref a, ref d);
if (root.left.value != 4)
throw new ApplicationException("New Root --> left --> value != 4 as expected");
Console.WriteLine("New root --> left node has correct value of 4");
if ((root.left.right.parent != root.left))
throw new Exception("and root --> left --> right has incorrect parent");
Console.WriteLine("Root --> left --> right has the correct parent");
if (root.left.right.value != 1)
throw new ApplicationException("New Root --> left --> right --> value did not equal 1.");
Console.WriteLine("New Root --> Left --> right has the correct value of 1");
if (root.left.right.left.value != 7)
throw new ApplicationException("New Root --> left --> right --> left --> value was not 7 as expected.");
Console.WriteLine("New Root --> left --> right --> left.value had a value of 7 as expected");
if (root.left.right.left.parent != root.left.right)
throw new ApplicationException("New Root --> left --> right --> left --> parent was not root --> left --> right as expected");
Console.WriteLine("New Root --> Left --> right --> left has the correct value of 7 and expected parent");
Console.Read();
}
Please take a look at this line:
if (n1.right != null)
{
n1.right.parent = n2;
}
If n2 is the right child of the n1, as in this case, n1.rightisn2, so n1.right.parent = n2 is actually n2.parent = n2 which causes the loop.
To solve the problem you have to either make copies of the nodes and then replace them, or try to do both swaps atomically and independently.
If I am understanding what your swap function should be doing, it should be as simple as this:
public static void swap(Node n1, Node n2)
{
Node left1 = n1.left;
Node left2 = n2.left;
Node right1 = n1.right;
Node right2 = n2.right;
Node parent1 = n1.parent;
Node parent2 = n2.parent;
n1.left = left2;
n2.left = left1;
n1.right = right2;
n2.right = right1;
n1.parent = parent2;
n2.parent = parent1;
}
What I think you need to do is simple swap n1's left and right with n2's left and right. No need for ref's either, since its a reference type and not a value type.
How do I print out a given node from my binary search tree using a method called PrintNodes.
Here is my Node class:
public class Node
{
public string data;
public Node left;
public Node right;
public Node(string data)
{
this.data = data;
}
}
And here is my Binary Search Tree Class:
class BinarySearchTree
{
public Node root, current;
public BinarySearchTree()
{
this.root = null;
}
public void AddNode(string a) // code to insert nodes to the binary search tree
{
Node newNode = new Node(a); //create a new node
if (root == null) // if the tree is empty new node will be the root node
root = newNode;
else
{
Node previous;
current = root;
while (current != null)
{
previous = current;
if (string.Compare(a, current.data) < 0) //if the new node is less than the current node
{
current = current.left;
if (current == null)
previous.left = newNode;
}
else //if the new node is greater than the current node
{
current = current.right;
if (current == null)
previous.right = newNode;
}
}
}
}
This is the what I have so far for my PrintNodes method, but I just realised that its not actually printing the given node its just printing the string that I pass into the method(I'm really new to this as you can see)
public String PrintNodes(string a)
{
string Output = "";
if (a != null)
{
Output += "Node: " + a;
}
else
{
Output += "There is no node " + a;
}
return Output;
}
I know I have to somehow compare the string that is passed into the method to the node I am trying to print but I have no clue what to do my mind has gone blank.
Your Find method would look something like this:
public Node Find(key, root)
{
Node current-node = root;
while (current-node != null)
{
if (current-node.data == key)
return current-node;
else if (key < current-node.data)
current-node = current-node.left;
else
current-node = current-node.right;
}
return null;
}
Your PrintNodes method could then be:
public String PrintNodes(string a)
{
string Output = "";
Node theNode = Find(a);
if (Node != null)
{
Output += "Node: " + theNode.data;
}
else
{
Output += "There is no node " + a;
}
return Output;
}
Cheers
EDIT: I assume that your Node object will have some other "payload" attached to it, as right now you're simply printing the search string if found :-)
I believe that you need to find some string in the tree and print it.
if it is
here is a pseudo code
public String PrintNodes(string a , Node root)
{
string Output = "";
if( a == null )
return "string is empty";
Node curent;
curent = root;
while( curent != null )
{
compVal = string.Compare(a, current.data)
if ( compVal < 0 )
{
//goto leftNode
curent = curent.left
}
else if ( compVal > 0 )
{
//goto rightNode
curent = curent.right
}
else
{
//this is it
break;
}
}
if curent == null
return "string not found";
else
return
curent.data;
}