Recursively Adding Nodes to a custom TreeMap - java

Hello I am attempting to build my own TreeMap data structure. I have an add method that passes a Key and Value, I then have another method called insert that will recursively add the node to the tree. I keep getting a stackoverflow error.
I am unsure how to resolve this error I've re-written my insert method a few times and tried passing parent Nodes into the method. Can someone explain the logic behind what should be passed into the insert method or how my code may possibly still work?
Is the best option here to utilize recursion to add nodes to my tree? or can I accomplish the same thing with a while loop?
Any help is appreciated thank you!
public boolean add(K key, V value)
{
//root is declared as a class level variable in my Map class
if (root == null) {
curSize++;
root = new Node(key, value);
root.parent = null;
return true;
}
//Creating a new Node with the passed arguments
Node n = new Node(key, value);
Node curNode = root;
//Calling insert method
if (curNode.insert(n, curNode)) {
curSize++;
return true;
} else {
return false;
}
}
protected boolean insert(Node curNode, K key, V value) {
int result = key.compareTo(curNode.key);
boolean x = false;
if (curNode.L == null && result < 0) {
curNode.L = new Node(key, value);
x = true;
}
if (curNode.R == null && result > 0) {
curNode.R = new Node(key, value);
x = true;
}
if (result == 0)
x = false;
if (curNode.L != null && result < 0)
insert(curNode.L, key, value);
if (curNode.R != null && result > 0)
insert(curNode.R, key, value);
return x;
}
//My Node class with its constructor, Insert method is inside this class.
private class Node {
public Node L;
public Node R;
public K key;
public V value;
public Node parent;
public Node(K k, V v) {
this.L = null;
this.R = null;
this.key = k;
this.value = v;
}

In your implementation of insert() you have
insert(Node curNode, K key, V value)
but, when you call it, you write
curNode.insert(n, curNode)
Am I missing something? It seems to me like this code shouldn't run. I believe you should be calling it as
insert(curNode, key, value);
Separately, you have
boolean x = true;
at the start of your insert() method, which can be replaced by return statements to avoid entering the recursive blocks after successfully adding a node. I would change your insert method to this:
int result = key.compareTo(curNode.key);
if (curNode.L == null && result < 0) {
curNode.L = new Node(key, value);
return true;
}
if (curNode.R == null && result > 0) {
curNode.R = new Node(key, value);
return true;
}
if (curNode.L != null && result < 0)
return insert(curNode.L, key, value);
if (curNode.R != null && result > 0)
return insert(curNode.R, key, value);
return false;
to avoid accidentally calling insert() when you do not need to.

You forget to use the return values in these calls of insert:
if (curNode.L != null && result < 0)
insert(curNode.L, key, value);
if (curNode.R != null && result > 0)
insert(curNode.R, key, value);
Should be:
if (curNode.L != null && result < 0)
x = insert(curNode.L, key, value);
if (curNode.R != null && result > 0)
x = insert(curNode.R, key, value);
But think of eliminating varibale x by using return statements.

Related

BST: return first entry larger than the key

I am writing to write a Java method that takes a binary search tree (BST) T and a key k, and returns the first entry larger than k that would appear in an inorder traversal. If k is absent or no key larger than k is present, return null. For example, when applied to the BST in the figure below you should return 29 if k = 23; if k = 32, you should return null.
http://imgur.com/fpNk9fT
The pseudo code is:
findFirstEntryLargerThanKey(BSTNode t, int key)
// go left
findFirstEntryLargerThanKey(t.left, key);
// visit the node
if t.nodeValue == key
key exists, set a boolean value to true
else if t.nodeValue > key
check if this node value is the first entry larger than key
// go right
findFirstEntryLargerThanKey(t.right, key);
The code that I have written uptil now:
boolean found = false;
int x = 0;
public Integer findFirstEntryLargerThanKey(BSTNode t, int key) {
// the scan terminates on an empty subtree
if (t != null) {
// descend left
findFirstEntryLargerThanKey(t.left, key);
// visit the node
if (t.nodeValue == key){
found = true;
}
else if (t.nodeValue > key && found == true && ? && ?){
x = t.nodeValue;
}
// descend right
findFirstEntryLargerThanKey(t.right, key);
return x;
}
return null;
}
I need help regarding the conditions that I have to use.
Do an in order traversal , which will print the tree key in ascending order . simultaneously keep comparing the key and print the first key that is greater than your key .. The time complexity will be less than O(n)
You can directly return the answer when you find it, since x is globally declared.
Your function should be something like this :
boolean found = false;
int x = 0;
public Integer findFirstEntryLargerThanKey(BSTNode t, int key) {
// the scan terminates on an empty subtree
if (t != null) {
// descend left
findFirstEntryLargerThanKey(t.left, key);
// visit the node
if (t.nodeValue == key){
found = true;
}
else if (t.nodeValue > key && found == true){
x = t.nodeValue;
return x;
}
// descend right
findFirstEntryLargerThanKey(t.right, key);
return x;
}
return null;
}
Or, do something like this :
int x = 0;
public Integer findFirstEntryLargerThanKey(BSTNode t, int key) {
// the scan terminates on an empty subtree
if (t != null) {
// descend left
findFirstEntryLargerThanKey(t.left, key);
// visit the node
if (t.nodeValue > key){
x = t.nodevalue;
return x;
}
// descend right
findFirstEntryLargerThanKey(t.right, key);
return x;
}
return null;
}
Lets try the usual key search with two extra steps:
* Whenever we go left from a parent to a child,
remember the parent as a potential answer.
* If the key is found and it has a right subtree,
then the answer is left-most (smallest) node of that subtree.
FindFirstEntryLargerThanKey(BSTNode t, int key) {
BSTNode result_so_far = null;
for (BSTNode cur = t; cur; ) {
if (key < cur->key) {
result_so_far = cur;
cur = cur->left;
}
else if (key == cur->key) {
if (cur->right) {
result_so_far = LeftMostNode(cur->right);
}
break;
}
else {
cur = cur->right;
}
}
return result_so_far;
}
try this out
public Integer findFirstEntryLargerThanKey(BSTNode t, int key) {
Integer x =null;
// the scan terminates on an empty subtree
if (t != null && x!=null) {
// descend left
findFirstEntryLargerThanKey(t.left, key);
// visit the node
if (t.nodeValue > key ||t.nodeValue==key){
x = t.nodeValue;
}
// descend right
findFirstEntryLargerThanKey(t.right, key);
}
return x;
}

for loop encounter return statement in recursion method

public void delete(String key) {
root = delete(root, key, 0);
}
public Node delete(Node x, String key, int d) {
if(x == null)
return null;
if(d == key.length())
x.val = null;
else {
char c = key.charAt(d);
x.next[c] = delete(x.next[c], key, d + 1);
}
//----------------
if(x.val !=null )
return x;
for (char c = 0;c < R ; c++ ) {
if(x.next[c] != null)
return x;
return null;
}
}
from BOOK Algoritm 4, TrieST.java
So what's happening? for loop can return x by many times; is it okay for return type method? If okay, then what is the final return value?
Once "return" is called, the function is terminated.
So the value returned by the function is either:
x if x.val != null
x if for the first c (ie c = 0), x.next[c] !=null
null otherwise
As said in the comments, there must be a typo, I guess
return null;
should be after the for loop. Then the function would return:
x if x.val != null
x if there is a c for which x.next[c] !=null
null otherwise

Why won't my delete function delete the node out of the BST?

I've spent hours trying to figure it out. I've checked and the delete function does find the node, but when I try to delete it by setting it as null or equal to a child node it doesn't change the tree at all when I print it out for a second time. Can anyone help me figure out what I've done wrong or at least guide me to what I need to do to fix it?
class BST {
Node root;
void BST () {
root = new Node("B");
insert (root, "A");
insert (root, "D");
insert (root, "C");
inOrder (root);
System.out.println (" ");
delete (root, "D");
//root.LEFT = null;
inOrder (root);
}
void insert (Node n, String newKEY) {
if (n.KEY.compareTo(newKEY) > 0) {
if (n.LEFT == null) n.LEFT = new Node(newKEY);
else if (n.LEFT != null && n.LEFT.KEY.compareTo(newKEY) < 0) n.LEFT = new Node(n.LEFT, newKEY, null);
else insert (n.LEFT, newKEY);
}
if (n.KEY.compareTo(newKEY) < 0) {
if (n.RIGHT == null) n.RIGHT = new Node(newKEY);
else if (n.RIGHT != null && n.RIGHT.KEY.compareTo(newKEY) > 0) n.RIGHT = new Node(null, newKEY, n.RIGHT);
else insert (n.RIGHT, newKEY);
}
else if (n.KEY.compareTo(newKEY) == 0) n.C++;
}
void delete (Node n, String s) {
// Visit, check if proper node, if so then delete
if (n.KEY.compareTo(s) == 0) {
System.out.println (n.KEY);
// Deleting a node with no children
if (n.LEFT == null && n.RIGHT == null) n = null;
// Deleting a node with only left child
else if (n.RIGHT == null) n = n.LEFT;
// Deleting a node with only right child
else if (n.LEFT == null) n = n.RIGHT;
// Deleting a node with two children
else deleteNode_Two_Children (n, s);
}
// Left
else if (n.KEY.compareTo(s) > 0) delete (n.LEFT, s);
// Right
else if (n.KEY.compareTo(s) < 0) delete (n.RIGHT, s);
}
boolean find (Node n, String s) {
if (n.KEY.compareTo(s) > 0) {
if (n.LEFT == null) return false;
else if (n.LEFT != null && n.LEFT.KEY.compareTo(s) < 0) return false;
else find (n.LEFT, s);
}
if (n.KEY.compareTo(s) < 0) {
if (n.RIGHT == null) return false;
else if (n.RIGHT != null && n.RIGHT.KEY.compareTo(s) > 0) return false;
else find (n.RIGHT, s);
}
else if (n.KEY.compareTo(s) == 0) return true;
return false;
}
void deleteNode_Two_Children (Node n, String st) {
Node s = getSuccessor(n);
n = new Node (n.LEFT, s.KEY, s.C, n.RIGHT);
delete (s, st);
}
Node getSuccessor (Node n) {
Node temp = new Node();
while (n.LEFT != null) {
temp = n.LEFT;
n = temp;
}
return temp;
}
void inOrder (Node n) {
// Left
if (n.LEFT != null) inOrder (n.LEFT);
// Visit
System.out.print (n.KEY + " - " + n.C + ", ");
// Right
if (n.RIGHT != null) inOrder (n.RIGHT);
}
public static void main(String args[]){
BST t = new BST();
t.BST();
}
}
class Node {
String KEY;
int C;
Node LEFT;
Node RIGHT;
Node (String key) {
KEY = key;
C = 1;
LEFT = null;
RIGHT = null;
}
Node (Node L, String key, Node R) {
LEFT = L;
RIGHT = R;
KEY = key;
C = 1;
}
Node (Node L, String key, int c, Node R) {
LEFT = L;
RIGHT = R;
KEY = key;
C = c;
}
Node () {
KEY = null;
C = 0;
LEFT = null;
RIGHT = null;
}
// If 'this' is less than 'other', a negative number will be returned,
// 0 if equal
// Positive number if 'this' is greater.
int compare (Node other) {
return this.KEY.compareTo(other.KEY);
}
boolean equals (Node other) {
return this.KEY.equals(other.KEY);
}
}
The problem is your assumption that setting n to null will remove the node. Consider the following:
Object x = new Object();
public void someMethod(Object o) {
o = null;
}
This won't modify x. Java is pass-by-value, where o is the reference to some Object. You can certainly modify the internals of o through o's methods:
o.setValue(1);
This works because the value of o is really some address on the heap, which isn't being modifed. You can't overwrite o itself (eg, you can't set it to null or a new Object()). In order for you to delete a node, you must find the node's parent and set it's left or right child (whichever one you with to remove) and set that to null. Also, if that node has children, you have to make sure they aren't removed just because their parent is removed.

Java binary search tree - incorrectly working insert method

I've a binary search tree homework in Java where I was given complete Tree and Node classes and a SearchTree class in which I'm to complete the search and insert methods. The search is supposed to return the value of the node corresponding the searched key.
Here is the Tree class and here the Node class. My search and insert methods are below.
It seems I'm getting close, but test insert of key 0 and value 2 into Tree[Node[0,1,null,null]] results in Tree[Node[0,1,null,null] rather than the correct Tree[Node[0,2,null,null]]. What am I not understanding here?
public static Object search(Tree tree, int key) {
Node x = tree.getRoot();
while (x != null) {
if (key == x.getKey()) {
return x.getValue();
}
if (key < x.getKey()) {
x = x.getLeft();
} else {
x = x.getRight();
}
}
return null;
}
public static void insert(Tree tree, int key, Object value) {
if (tree.getRoot() == null) {
tree.setRoot(new Node(key, value));
}
Node juuri = tree.getRoot();
while (juuri != null) {
if (key == juuri.getKey()) {
return;
} else if (key < juuri.getKey()) {
if (juuri.getLeft() == null) {
juuri.setLeft(new Node(key, value));
return;
} else {
juuri = juuri.getLeft();
}
} else {
if (juuri.getRight() == null) {
juuri.setRight(new Node(key, value));
return;
} else {
juuri = juuri.getRight();
}
}
}
}
Well the issue I am seeing is that key values in your tree are unique. In this if statement you leave your insert method without adding a node if you see that the key is already in the tree.
if (key == juuri.getKey()) {
return;
}
In your example (if I understand it right) 0 is already in the tree so nothing changes when inserting 0 again. Based on your example, I am assuming you want to do an update on a node if the key is the same. So this code would do it.
if (key == juuri.getKey()) {
juuri.setValue(value);
return;
}

Put method of a TreeMap implementation

I'm working on an implementation of TreeMap(called MyTreeMap) and I'm having a lot of trouble with the put method. I was hoping someone could look at my code and point me in the right direction as to where things start to go wrong.
public class MyTreeMap<K extends Comparable<? super K>,V> extends AbstractMap<K,V> {
K key;
V value;
int height;
MyTreeMap<K,V> left,right;
int size;
public V put(K key, V value) {
int compareValue = this.key.compareTo(key);
if(!this.containsKey(key)) {
if(this.key == null) {
this.key = key;
this.value = value;
}
if(this.isLeaf() || this.isEmpty()) {
if(this.key.compareTo(key) > 0)
this.left = new MyTreeMap<K,V>(key,value,null,null);
else
this.right = new MyTreeMap<K,V>(key,value,null,null);
if(left.height > right.height + 1 || right.height > left.height + 1)
restructure(this);
this.size++;
setHeight();
return null;
}
else {
if(compareValue > 0)
return this.left.put(key, value);
else
return this.right.put(key, value);
}
}
else {
if(compareValue == 0) {
V temp = this.value;
this.value = value;
return temp;
}
else if(compareValue < 0)
return this.right.put(key, value);
else
return this.left.put(key, value);
}
}
I think your logic is a bit inside-out, and as a result is a lot more complicated than it needs to be: the top level if should probably be looking at the compareValue, not doing the containsKey check.
Logic should be:
if compareValue==0 then this means you have found the right key, so just update the value and return
otherwise check the left or right branch as appropriate (depending on sign of compareValue):
if the branch is null, then turn it into a new TreeMap branch containing your key and value (you are now done)
otherwise (branch is not null), call put recursively on this branch. If you like you can do rebalancing logic after this call.
P.S. I suggest not allowing null keys in a TreeMap, it will make your life simpler, and will avoid the need to do null checks on keys

Categories

Resources