I have a very simple implemention of BST in C#. The code:
class Node
{
public int? value;
public Node parent;
public Node left;
public Node right;
public Node(int? value, Node parent = null)
{
this.value = value;
this.parent = parent;
}
}
class BST
{
public Node root;
public List<Node> tree = new List<Node>();
public BST(int? value = null)
{
if (value != null)
{
this.root = new Node(value);
this.tree.Add(this.root);
}
}
public Node insert(int value)
{
Node node = this.root;
if (node == null)
{
this.root = new Node(value);
this.tree.Add(this.root);
return this.root;
}
while (true)
{
if (value > node.value)
{
if (node.right != null)
{
node = node.right;
}
else
{
node.right = new Node(value, node);
node = node.right;
break;
}
}
else if (value < node.value)
{
if (node.left != null)
{
node = node.left;
}
else
{
node.left = new Node(value, node);
node = node.left;
break;
}
}
else
{
break;
}
}
return node;
}
}
class Program
{
static void Main()
{
BST superTree = new BST(15);
superTree.insert(14);
superTree.insert(25);
superTree.insert(2);
}
}
My Question is regarding the "Insert" method of the BST class.
How exactly its "return" work when I just call it in the main method?
How does it know to put that "node" on the "left"? I am not referencing "root.left" anywhere but somehow it gets properly inserted.
I realized at some point that some kind of recursion occurs there, but its been like 6 hours and I still can't understand how this method properly works.
I appreaciate any explanation of that "insert" method.Thanks.
Node node = this.root;
Your code always starts with the root, because of this line. It's only after node is no longer null that node be re-assigned to something other than root. The rest of the code works on node.left, but because your code begins with root as above, node.left is actually referencing root at the start.
Related
Could you please help to understand, how I can modify AddFront method in LinkedList and set a tail and reference to the previous node (for example tail.Previous)? The tail should point out the first added element (last element in the LinkedList) and tail.Previous to second added element (second element from the end) and be able to access elements from tail to the head using Previous property.
Thanks.
public class Node
{
public int Data;
public Node Next;
public Node Previous;
public Node(int x)
{
Data = x;
Next = null;
Previous = null;
}
public class MyLinkedList
{
private int Length { get; set; }
private Node head = null;
private Node tail = null;
public void AddFront(int x)
{
var newNode = new Node(x);
newNode.Next = head;
if (head != null)
{
head.Previous = newNode;
}
//Somewhere here tail and tail.Previous should be set
head = newNode;
Length++;
}
}
Just add the else case:
if (head != null)
{
head.Previous = newNode;
}
else
{
tail = newNode;
}
I have only started learning Data Structures so please bear my stupidity, I am trying to develop my own version of BST, I can't get why there is a need of a parent Node? Shouldn't this work just fine.
class BST
{
private Node root;
public BST()
{
root = null;
}
public void insert(int value)
{
Node temp = new Node();
temp.value = value;
if (root == null)
{
root = temp;
return;
}
Node current = root;
while (current != null)
{
if (value <= current.value)
{
current = current.lc;
}
else
{
current = current.rc;
}
}
current = temp;
}
}
class Node
{
public Node lc;
public int value;
public Node rc;
}
There is definitely something that I am missing and I can't grasp or get what it is, when current is null, we are already onto where we need to insert the node, why then do we need a parent node.
This may work
class BST
{
private Node root = null;
public void insert(int value)
{
Node temp = new Node { value = value };
if (root == null)
{
root = temp;
return;
}
var current = root;
while (current != null)
{
if (value <= current.value)
{
if (current.lc == null)
{
current.lc = temp;
break;
}
current = current.lc;
}
else
{
if (current.rc == null)
{
current.rc = temp;
break;
}
current = current.rc;
}
}
}
}
class Node
{
public Node lc;
public int value;
public Node rc;
}
You are mixing variables with references to fields/variables. The current variable holds the value of the lc or rc field (the copy of the field). Setting the variable does not set the corresponding field, just assigns another value to the variable.
Hence the line
current = temp;
does not insert the node in the BST.
What you are trying to do is possible with C#7.0 introduced ref locals and returns and C#7.3 introduced improvements which allow to reassign ref local variables.
The ref local variables are exactly what is your intention - they contain the location (reference, address) of some other field / variable. So the following works (requires C#7.3!):
public void insert(int value)
{
ref Node nodeRef = ref root;
while (nodeRef != null)
{
if (value <= nodeRef.value)
nodeRef = ref nodeRef.lc;
else
nodeRef = ref nodeRef.rc;
}
nodeRef = new Node { value = value };
}
Note the usage of ref keyword. You use nodeRef = ref … to assign a reference (address) of a variable (in this case either root or some node lc or rc field), and nodeRef = … to assign a value to the variable pointed by the nodeRef.
You are setting "null" to some instance.
In your while loop current eventually becomes null, and you are missing the connection between nodes.
To fix this issue you should keep the last node of your tree.
You can try the below :
class BST
{
private Node root;
public BST()
{
root = null;
}
public void insert(int value)
{
root = insert(root, value);
}
private Node insert(Node node, int value) {
// if the given node is null it should be new node
if (node == null) {
node = new Node();
node.value = value;
return node;
}
if (value < node.value)
// if our value lower then current value then we will insert left node recursively
node.lc = insert(node.lc, value);
else if (value > node.value)
// if our value higher then current value then we will insert right node recursively
node.rc = insert(node.rc, value);
return node;
}
public void print() {
print(root);
}
private void print(Node node) {
if (node != null) {
print(node.lc);
Console.WriteLine(node.value);
print(node.rc);
}
return;
}
}
public static void main(String[] args) {
BST bst = new BST();
bst.insert(5);
bst.insert(25);
bst.insert(15);
bst.insert(4);
bst.print();
}
The output is :
4
5
15
25
I have a program, and i want to remove a node from the tree. Ok, i can remove, but when i want to save it again it shows me a error.
public void InsertNode(string value)
{
root = InsertNode(value, root);
}
private Node InsertNode(string value, Node node)
{
if (node == null)
{
node = new Node(value, null, null);
}
else
{
if (node.value.CompareTo(value) > 0) ---- The error is in this line
{
node.lChild = InsertNode(value, node.lChild);
}
else
{
node.rChild = InsertNode(value, node.rChild);
}
}
return node;
}
I'm having problems trying to write a reverse recursive method for a LinkedList class I created in C#.
The LinkedList has 2 pointers in it one for the head and the other for the tail:
public class Node
{
public object data;
public Node next;
public Node(object Data)
{
this.data = Data;
}
}
public class LinkedList
{
Node head;
Node tail;
public void Add(Node n)
{
if (head == null)
{
head = n;
tail = head;
}
else
{
tail.next = n;
tail = tail.next;
}
}
Now, the recursive reverse function goes like this:
public void reverse_recursive()
{
Node temp_head = head;
if (temp_head == tail)
{
return;
}
while (temp_head != null)
{
if (temp_head.next == tail)
{
tail.next = temp_head;
tail = temp_head;
reverse_recursive();
}
temp_head = temp_head.next;
}
}
I'm having 2 troubles with it: first, a logic problem, I know that head doesn't point to the first node after the reverse. The second problem is that i probably do something wrong with the null pointer so the program crashes.
I also give you the main program:
class Program
{
static void Main(string[] args)
{
LinkedList L = new LinkedList();
L.Add(new Node("first"));
L.Add(new Node("second"));
L.Add(new Node("third"));
L.Add(new Node("forth"));
L.PrintNodes();
L.reverse_recursive();
L.PrintNodes();
Console.ReadLine();
}
}
Thank you for helping!!
public void Reverse()
{
this.Reverse(this.head);
}
private void Reverse(Node node)
{
if (node != null && node.next != null)
{
// Create temporary references to the nodes,
// because we will be overwriting the lists references.
Node next = node.next;
Node afterNext = node.next.next;
Node currentHead = this.head;
// Set the head to whatever node is next from the current node.
this.head = next;
// Reset the next node for the new head to be the previous head.
this.head.next = currentHead;
// Set the current nodes next node to be the previous next nodes next node :)
node.next = afterNext;
// Keep on trucking.
this.Reverse(node);
}
else
{
this.tail = node;
}
}
public void reverse()
{
reverse_recursive(tail);
Node tmp = tail;
tail = head;
head = tmp;
}
public void reverse_recursive(Node endNode)
{
Node temp_head = head;
if (temp_head == endNode)
{
return;
}
while (temp_head != null)
{
if (temp_head.next == endNode)
{
break;
}
temp_head = temp_head.next;
}
endNode.next = temp_head;
temp_head.next = null;
reverse_recursive(temp_head);
}
See also this
Another option over here.
class Program{
static void Main(string[] args)
{
LinkedList L = new LinkedList();
L.Add(new Node("first"));
L.Add(new Node("second"));
L.Add(new Node("third"));
L.Add(new Node("forth"));
L.PrintNodes();
L.reverse_recursive();
Console.WriteLine("---------------------");
L.PrintNodes();
Console.ReadLine();
}
}
public class Node
{
public object data;
public Node next;
public Node(object Data)
{
this.data = Data;
}
}
public class LinkedList
{
Node head;
Node tail;
public void Add(Node n)
{
if (head == null)
{
head = n;
tail = head;
}
else
{
tail.next = n;
tail = tail.next;
}
}
public void PrintNodes()
{
Node temp = head;
while (temp != null)
{
Console.WriteLine(temp.data);
temp = temp.next;
}
}
private LinkedList p_reverse_recursive(Node first)
{
LinkedList ret;
if (first.next == null)
{
Node aux = createNode(first.data);
ret = new LinkedList();
ret.Add(aux);
return ret;
}
else
{
ret = p_reverse_recursive(first.next);
ret.Add(createNode(first.data));
return ret;
}
}
private Node createNode(Object data)
{
Node node = new Node(data);
return node;
}
public void reverse_recursive()
{
if (head != null)
{
LinkedList aux = p_reverse_recursive(head);
head = aux.head;
tail = aux.tail;
}
}
}
Hope it helps
A second variant
private void p_reverse_recursive2(Node node)
{
if (node != null)
{
Node aux = node.next;
node.next = null;
p_reverse_recursive2(aux);
if (aux != null)
aux.next = node;
}
}
public void reverse_recursive()
{
if (head != null)
{
Node aux = head;
head = tail;
tail = aux;
p_reverse_recursive2(tail);
}
}
Variation on a theme...
public Node Reverse(Node head)
{
if(head == null)
{
return null;
}
Node reversedHead = null;
ReverseHelper(head, out reversedHead);
return reversedHead;
}
public Node ReverseHelper(Node n, out Node reversedHead)
{
if(n.Next == null)
{
reversedHead = n;
return n;
}
var reversedTail = ReverseHelper(n.Next, out reversedHead);
reversedTail.Next = n;
n.Next = null;
return n;
}
}
I was just playing with similar brain teaser with the only difference that LinkedList class only has a definition for head and all the rest of the nodes are linked there. So here is my quick and dirty recursive solution:
public Node ReverseRecursive(Node root)
{
Node temp = root;
if (root.next == null)
return root;
else
root = ReverseRecursive(root.next);
temp.next = null;
Node tail = root.next;
if (tail == null)
root.next = temp;
else
while (tail != null)
{
if (tail.next == null)
{
tail.next = temp;
break;
}
else
tail = tail.next;
}
return root;
}
i am working on linked list.. i successfully inserted and deleted a node at first node.. but when i try to insert node at last .. it gives an error "Object reference not set to an instance of an object"
My logic is correct but visual studio is generating an exception dont know why
please help me out..
Full code is given below
class MyList
{
private Node first;
private Node current;
private Node previous;
public MyList()
{
first = null;
current = null;
previous = null;
}
public void InsertLast(int data)
{
Node newNode = new Node(data);
current = first;
while (current != null)
{
previous = current;
current = current.next;
}
previous.next = newNode;
newNode.next = null;
}
public void displayList()
{
Console.WriteLine("List (First --> Last): ");
Node current = first;
while (current != null)
{
current.DisplayNode();
current = current.next;
}
Console.WriteLine(" ");
}
}
class Node
{
public int info;
public Node next;
public Node(int a)
{
info = a;
}
public void DisplayNode()
{
Console.WriteLine(info);
}
}
class Program
{
static void Main(string[] args)
{
MyList newList = new MyList();
newList.InsertLast(10);
newList.InsertLast(20);
newList.InsertLast(30);
newList.InsertLast(40);
newList.displayList();
Console.ReadLine();
}
}
Basically you will have to deal with the case of an empty list. In your current code when the list is empty you have previous, current, and first all equal to null. So you're getting an error because you're attempting to assign previous.next() a value when previous equals null.
If the list is empty, first will be equal to null and your code will raise exception when you try to do this previous.next = newNode; because the previous is also null. when adding first node, you will have to add the new element as first, so rewrite the code like this:
public void InsertLast(int data)
{
Node newNode = new Node(data);
if (first == null)
{
first = newNode;
}
else
{
current = first;
while (current != null)
{
previous = current;
current = current.next;
}
previous.next = newNode;
}
newNode.next = null;
}
EDIT: You can implement it something like this but take care if the fist is null and the case when there is only first node. Check the method:
public void RemoveLast()
{
if (first != null)//there is no point in removing since the list is empty
{
if (first.next == null) //situation where list contains only one node
first = null;
else //all other situations
{
current = first;
while (current.next != null)
{
previous = current;
current = current.next;
}
previous.next = null;
}
}
}