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
Related
here i have the following code and input that prints a tree structure. My question is how can i make it so that the nodes and leafs that have the value "Unavailable" are skipped from being printed.
namespace Tree{public class TreeNode<T>
{
private T value;
private bool hasParent;
private List<TreeNode<T>> children;
public TreeNode(T value)
{
if (value == null)
{
throw new ArgumentNullException("Cannot insert null value");
}
this.value = value;
this.children = new List<TreeNode<T>>();
}
public T Value
{
get
{
return this.value;
}
set
{
this.value = value;
}
}
public int ChildrenCount
{
get
{
return this.children.Count;
}
}
public void AddChild(TreeNode<T> child)
{
if (child == null)
{
throw new ArgumentNullException("Cannot insert null value");
}
if (child.hasParent)
{
throw new ArgumentException("The node already has a parent");
}
child.hasParent = true;
this.children.Add(child);
}
public TreeNode<T> GetChild(int index)
{
return this.children[index];
}
}
public class Tree<T>
{
private TreeNode<T> root;
public Tree(T value)
{
if (value == null)
{
throw new ArgumentNullException("Cannot insert null value");
}
this.root = new TreeNode<T>(value);
}
public Tree(T value, params Tree<T>[] children) : this(value)
{
foreach (Tree<T> child in children)
{
this.root.AddChild(child.root);
}
}
public TreeNode<T> Root
{
get
{
return this.root;
}
}
private void PrintDFS(TreeNode<T> root, string spaces)
{
if (this.root == null)
{
return;
}
Console.WriteLine(spaces + root.Value);
TreeNode<T> child = null;
for (int i = 0; i < root.ChildrenCount; i++)
{
child = root.GetChild(i);
PrintDFS(child, spaces + " ");
}
}
public void TraverseDFS()
{
this.PrintDFS(this.root, string.Empty);
}
}
public static class TreeExample
{
static void Main()
{
Tree<string> tree =
new Tree<string>("John",
new Tree<string>("Jasmine",
new Tree<string>("Jay"),
new Tree<string>("Unavailable")),
new Tree<string>("Unavailable",
new Tree<string>("Jack"),
new Tree<string>("Jeremy")),
new Tree<string>("Johanna")
);
tree.TraverseDFS();
}
}}
right now it prints :(John, (Jasmine, (Jay), (Unavailable)), (Unavailable, (Jack, (Jeremy))), (Johanna))
I need it to print :(John, (Jasmine, (Jay)), (Johanna))
So basically skip every leaf with the value "Unavailable" and every node with the value "Unavailable" and all children from that node
Thanks !
This should work:
private void PrintDFS(TreeNode<T> root, string spaces)
{
if (this.root == null
|| "Unavailable" == root.Value.ToString())
{
return;
}
...
The accepted answer is a literally correct answer to the question, but it bakes in logic about what to do with the tree into the tree itself. A tree is a kind of collection or data structure, and you don't often see a List or Dictionary that is able to print itself. Instead the collection provides the right methods to get or change its contents so that you can do what you want.
In your case, you could do something like the following:
public enum TreeVisitorResult {
SkipNode,
Continue
}
// the following two methods inside Tree<T>:
public void VisitNodes(Func<TreeNode<T>, int, TreeVisitorResult> visitor) {
VisitNodes(0, this.root, visitor);
}
private void VisitNodes(int depth, TreeNode<T> node,
Func<TreeNode<T>, int, TreeVisitorResult> visitor) {
if (node == null) {
return;
}
var shouldSkip = visitor(node, depth);
if (shouldSkip == TreeVisitorResult.SkipNode) {
return;
}
TreeNode<T> child = null;
for (int i = 0; i < node.ChildrenCount; i++) {
child = node.GetChild(i);
VisitNodes(depth + 1, child, visitor);
}
}
If you had this method, you could write the Print method outside of the Tree classes, as:
tree.VisitNodes((treeNode, depth) => { // <- this lambda will be called for every node
if (treeNode.Value == "Unavailable") { // <- no need to ToString or cast here, since
// we know that T is string here
return TreeVisitorResult.SkipNode;
} else {
var spaces = new string(' ', depth * 3);
Console.WriteLine(spaces + treeNode.Value);
}
});
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.
I've tried to implement a binary-search-tree(BST) insert using the following method but i really don't get why i get the value instead of the actual "reference" to the node.
I've done other implementations that worked fine but I really want to understand why instead of getting the pointer to let's say node.m_left I get just it's value (null).
How can I get that without resorting to unsafe code ?
The reason i'm choosing this way is because searching and inserting are closely related and i don't want to implement the same thing twice.
public void Add(int value)
{
if (root == null)
{
root = new Node(value);
return;
}
Node parent = null ,
res;
//finding the correct place
res = Find(value, root, ref parent);
if (res == null) //probably redunant
{
//once found create a node and asign it's parent
res = new Node(value);
res.m_parent = parent;
}
//EvaluateAVT(res);
}
private Node Find(int value, Node node, ref Node parent,bool justfind = false)
{
if (node.Data == value && justfind)
{
return node;
}
if (node.Data >= value)
{
if (node.m_left == null)
{
parent = node;
return node.m_left;
}
return Find(value,node.m_left,ref parent ,justfind);
}
else
{
if (node.m_right == null)
{
parent = node;
return node.m_right;
}
return Find(value, node.m_right, ref parent, justfind);
}
}
I'm trying to make a remove method in my LinkedList by entering a single value and then all of the values that match that value will be deleted from the Node.
Cant seem to solve it.
What is wrong?
public void RemoveByValue(int value)
{
if (start == null)
return;
Node runner = start;
while (runner.Next != null)
{
Node current = FindValue(value);
if (current == null)
{
return;
}
current.Next = runner.Next;
}
}
private Node FindValue(int value)
{
Node runner = start;
while (runner.Next.Value != value)
{
runner = runner.Next;
}
return runner;
}
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;
}
}
}