Implementation of binary search tree add algorithm - java

I have to implement an add method for a BST in java, but can not get my add function to work. Could someone help me out?
private boolean add(E x, BinaryNode<E> currentNode){
if (currentNode == null){
currentNode = new BinaryNode<>(x);
size++;
return true;
}
if (currentNode.element.compareTo(x) == 0){
return false;
}
else if((currentNode.element.compareTo(x) < 0)){
if(currentNode.left == null){
currentNode.left = new BinaryNode<>(x);
size++;
return true;
} else {
add(x, currentNode.left);
}
}
else if(currentNode.element.compareTo(x) > 0){
if(currentNode.right == null){
currentNode.right = new BinaryNode<>(x);
size++;
return true;
} else {
add(x, currentNode.right);
}
}
return false;
}
public boolean add(E x){
return this.add(x, root);
}

One problem I see is that when you assign the root element you assign it to a local variable. This obviously doesn't work.
private boolean add(E x, BinaryNode<E> currentNode){
/////// REMOVE
if (currentNode == null){
currentNode = new BinaryNode<>(x);
size++;
return true;
}
///////
And add this
public boolean add(E x){
if( root == null ) {
root = new BinaryNode<>(x);
size++;
return true;
} else
return this.add(x, root);
}

Basically, the root of subtree might change, and this is a recursion, to make it work the return value should be the new root of the subtree, despite it changed or not.
Following are the add() method taken from my BST impl in Java, that with all test cases passed:
/**
* Add a new value.
*
* #param v
*/
#Override
public void add(T v) {
root = add(root, v);
}
/**
* Add to a subtree start from given node.
*
* #param current root of a subtree to add node to,
* #param v
* #return the new root of subtree,
*/
protected BSTNode<T> add(BSTNode<T> current, T v) {
if (current == null) { // subtree is empty,
size++;
return new BSTNode<>(v);
}
// compare,
int compareFlag = v.compareTo(current.value);
// check this or subtree,
if (compareFlag < 0) { // smaller, go to left subtree,
current.left = add(current.left, v);
} else if (compareFlag > 0) { // larger, go to right subtree,
current.right = add(current.right, v);
} else { // equals, ignore it,
}
return current;
}

Related

Unusual Java implementation of red/black tree node insertion

I'm writing a program for class in Java regarding red/black trees. I've got a good understanding of how they usually work, and am supposed to use a recursive insertion method. What I would typically use is below, to match my professor's Node class. In regards to color, a 0 is black, a 1 is red. The Node class given to us does not deal with keys at all.
private static void put(int val, int col)
{ root = put(root, val, col); }
private static Node put(Node n, Integer val, int col)
{
if (n == null){
Node t=new Node(val);
t.setColor(1);
return t;
}
int cmp = val.compareTo(n.getValue());
if (cmp < 0) n.setLeft(put(n.getLeft(), val, col));
else if (cmp > 0) n.setRight(put(n.getRight(), val, col));
else n.setColor(col);
if (isRed(n.getRight()) && !isRed(n.getLeft())) n = rotateLeft(n);
if (isRed(n.getLeft()) && isRed(n.getLeft().getLeft())) n = rotateRight(n);
if (isRed(n.getLeft()) && isRed(n.getRight())) flipColors(n);
return n;
}
However, the catch is that we are supposed to return a boolean value--if the user inserts a duplicate value as is already on the tree, we return false and don't attach the node. Otherwise, we attach them and return true; the code given to us for this is below, but is not recursive (part of the project requirements). And while I hadn't implemented a way of balancing or rotating properly, the returned boolean part works.
public boolean insertNode(Node node) {
//Here is just an example of setting colors for a node. So far, it is in green color. But you need to modify the code to dynamically adjust the color to
//either RED or BLACK according to the red-black logic
Node current_node;
// if the root exists
if (root == null) {
root = node; // let the root point to the current node
root.setColor(Node.BLACK);
return true;
} else {
current_node = root;
node.setColor(1);
while (current_node != null) {
int value = current_node.getValue();
if (node.getValue() < value){ // go to the left sub-tree
if (current_node.getLeft() != null) // if the left node is not empty
current_node = current_node.getLeft();
else{ // put node as the left child of current_node
current_node.setLeft(node);
node.setParent(current_node);
current_node = null; }
//System.out.println("Left:"+current_node);
}
else if (node.getValue() > value){ // go to the right
if (current_node.getRight() != null) // if the right node is not empty
current_node = current_node.getRight();
else{ // put node as the right child of current_node
current_node.setRight(node);
node.setParent(current_node);
current_node = null; }
//System.out.println("Right: "+current_node);
}
else{
//System.out.println("Else: "+current_node);
return false; }
//if(current_node!=null&&current_node.getLeft()!=null&&current_node.getRight()!=null&&current_node.getLeft().isRed()&&current_node.getRight().isRed())
// flipColors(node);
}
}
if(node.getParent()!=null){
node=node.getParent();
System.out.println("Case: node has parent, val="+node.getValue());
}
if(node.getLeft()!=null&&node.getRight()!=null){
if((node.getRight().isRed())&&!node.getLeft().isRed())
node=rotateLeft(node);
if((node.getLeft().isRed())&&(node.getParent()!=null)&&(node.getParent().getLeft().getLeft()!=null)&&(node.getParent().getLeft().getLeft().isRed()))
node=rotateRight(node);
if((node.getLeft().isRed()) && (node.getRight().isRed()))
flipColors(node);
}
return true;
}
I wasn't able to find any comparable implementations online, and it seems that the boolean is necessary for the program's gui to work properly. If someone has a good suggestion for where to start, I would appreciate it!
For the recursive insertNode, I would suggest you the following: Create a function insertNode(Node node, Node current_node) which returns a boolean value. The idea is to always call the function insertNode for the currently investigated node, starting from the root node. If the node cannot be immediately added to current_node, the responsible node is called recursively to handle the node. I have provided you a short example based on your code (with some comments what the basic idea is, there is obviously some stuff missing). I hope, I got your question correctly and this helps you with your understanding.
public boolean insertNode(Node node) {
if (root == null) {
root = node;
root.setColor(Node.BLACK);
return true;
} else {
boolean result = insertNode(node, root);
if (result) {
//Some other important stuff to do...
}
return result;
}
}
public boolean insertNode(Node node, Node current_node) {
int value = current_node.getValue();
if (node.getValue() < value) {
if (current_node.getLeft() != null) {
// Investigate left
return insertNode(node, current_node.getLeft());
} else {
// Insert node left
return true;
}
} else if (node.getValue() > value) {
if (current_node.getRight() != null) {
// Investigate right
return insertNode(node, current_node.getRight());
} else {
// Insert node right
return true;
}
} else {
return false;
}
}
I now have the working functions, as below:
public boolean insertNode(Node node) {
if(root==null){
root=node;
root.setColor(Node.BLACK);
return true;
}
else
node.setColor(Node.RED);
return insertNode(node, root);
}
public boolean insertNode(Node node, Node cur){
if(node.getValue()<cur.getValue()){
if(cur.getLeft()!=null)
return insertNode(node, cur.getLeft());
else{
cur.setLeft(node);
node.setParent(cur);
handleInsertion(node);
return true; } }
else if(node.getValue()>cur.getValue()){
if(cur.getRight()!=null)
return insertNode(node, cur.getRight());
else{
cur.setRight(node);
node.setParent(cur);
handleInsertion(node);
return true; } }
else
return false;
}

Binary Search Tree - print out number of leaves

I have a program that is a binary search tree, the method searches for a specific word. I'm having two problems.
First is I would like to print the true or false from this method (basically making a system.out that says if the word was found), I'm assuming I would do it in main but I'm not sure how to do that.
The second problem is that I also need to print out how many leaves are in the tree, I was going to use a counter of some sort in the method but I didn't work.
My method is below but I also included it inside the class to help clear up any confusion.
Any help would be greatly appreciated.
public boolean check(BSTNode t,String key)
{
if (t == null) return false;
if (t.word.equals(key)) return true;
if (check(t.left,key)) return true;
if (check(t.right,key)) return true;
return false;
}
Whole class:
public class BST
{
BSTNode root;
BST() {
root = null;
}
public void add2Tree(String st)
{
BSTNode newNode = new BSTNode(st);
if (this.root == null) {
root = newNode;
} else {
root = addInOrder(root, newNode);
}
}
// private BSTNode insert2(BSTNode root, BSTNode newNode)
// {
// if (root == null)
// root = newNode;
// else {
// System.out.println(root.word + " " + newNode.word);
// if (root.word.compareTo(newNode.word) > 0)
// {
// root.left = (insert2(root.lTree, newNode));
// System.out.println(" left ");
// } else
// {
// root.rTree = (insert2(root.rTree, newNode));
// System.out.println(" right ");
// }
// }
// return root;
// }
public BSTNode addInOrder(BSTNode focus, BSTNode newNode) {
int comparevalue = 0;
if (focus == null) {
focus = newNode;
}
if (focus != null) {
comparevalue = newNode.word.compareTo(focus.word);
}
if (comparevalue < 0) {
focus.left = addInOrder(focus.left, newNode);
} else if (comparevalue > 0) {
focus.right = addInOrder(focus.right, newNode);
}
return (focus);
}
public void ioprint() {
System.out.println(" start inorder");
if (root == null)
System.out.println(" Null");
printinorder(root);
}
public void printinorder(BSTNode t) {
if (t != null) {
printinorder(t.left);
System.out.println(t.word);
printinorder(t.right);
}
}
public boolean check(BSTNode t,String key)
{
if (t == null) return false;
if (t.word.equals(key)) return true;
if (check(t.left,key)) return true;
if (check(t.right,key)) return true;
return false;
}
public BSTNode getroot(){
return root;
}
}
How to print true/false:
Create another class, call it Solution, Test or whatever you like.
Add a main method to it.
Populate your BST.
Call System.out.println(check(bstRoot, key)).
You can check this link to find out how to count the number of nodes in BST, it's pretty straightforward:
Counting the nodes in a binary search tree
private int countNodes(BSTNode current) {
// if it's null, it doesn't exist, return 0
if (current == null) return 0;
// count myself + my left child + my right child
return 1 + nodes(current.left) + nodes(current.right);
}

Remove a leaf from a BinaryTree

My code below will remove a tree with two children, or one child. But a leaf (a tree with zero children) I can't seem to crack. My BSTNode<E> also contains a .parent which identifies it's parent. I'm not sure if that would help with this implementation or not.
#Override
public E delete(E target) {
return delete(this.root, target);
}
private E delete(BSTNode<E> localRoot, E target) {
// ... Trying to delete an item that's not in the tree?
if (localRoot == null) {
return null;
}
int compareResult = c.compare(target, localRoot.data);
// Traverse the tree...
if (compareResult < 0) {
return delete(localRoot.left, target);
} else if (compareResult > 0) {
return delete(localRoot.right, target);
} else {
// Found the item! Oh boy here we go!
E retVal = localRoot.data;
/*
* Both left and right exist under the targeted node.
* Find the largest child under the right side of the node.
* Set the largest data to the 'deleted' node, then delete that node.
*/
if (localRoot.left != null && localRoot.right != null) {
/*
* Two children, find the smallest and assign it.
*/
localRoot.data = localRoot.right.data;
localRoot.right = findLargestChild(localRoot.right);
} else if (localRoot.left != null) {
localRoot.data = localRoot.left.data;
localRoot.left = findSmallestChild(localRoot.left);
} else if (localRoot.right != null) {
localRoot.data = localRoot.right.data;
localRoot.right = findLargestChild(localRoot.right);
} else {
/*
* TODO:
* Remove a leaf.
*/
System.out.println("Removing leaf..." + localRoot.data.toString());
localRoot = null;
}
return retVal;
}
}
Using localRoot.parent I was able to delete (null) the child of the localRoot's parent. This feels backwards, but it's passing JUnit Tests...
private E delete(BSTNode<E> localRoot, E target) {
// ... Trying to delete an item that's not in the tree?
if (localRoot == null) {
return null;
}
int compareResult = c.compare(target, localRoot.data);
// Traverse the tree...
if (compareResult < 0) {
return delete(localRoot.left, target);
} else if (compareResult > 0) {
return delete(localRoot.right, target);
} else {
// Found the item! Oh boy here we go!
E retVal = localRoot.data;
if (localRoot.right != null) {
/*
* Assign the largest value to the tree.
*/
localRoot.data = localRoot.right.data;
localRoot.right = findLargestChild(localRoot.right);
} else if (localRoot.left != null) {
/*
* Since the largest value didn't exist, assign the smallest.
*/
localRoot.data = localRoot.left.data;
localRoot.left = findSmallestChild(localRoot.left);
} else {
/*
* Remove a leaf.
*/
System.out.println("Removing leaf or left..." + localRoot.data.toString());
if (c.compare(target, localRoot.parent.left.data) == 0) {
localRoot.parent.left = null;
} else {
localRoot.parent.right = null;
}
}
return retVal;
}
}

Construct a no recursive insert method for binary tree

I have completed the recursive insert function and it works perfectly, but I can not get the non recursive solution to work.
public void insert(T item){
root= nonRecursive(root,item);
}
public BinaryTreeNode<T> nonRecursive(BinaryTreeNode<T> tree, T item){
if(root==null){
root=new BinaryTreeNode<T>(item);
return root;
}
else{
BinaryTreeNode<T> next = new BinaryTreeNode<T>();
Comparable<T> temp = (Comparable<T>) root.info;
if(temp.compareTo(item)== 0){
return null;
}
else if(temp.compareTo(item) > 0){
next=root.lLink;
}
else{
next=root.rLink;
}
while(next != null){
Comparable<T> temp2 = (Comparable<T>) next.info;
if(temp.compareTo(item) == 0){
return null;
}
else if(temp2.compareTo(item) > 0){
next=next.lLink;
}
else{
next=next.rLink;
}
}
next=new BinaryTreeNode<T>(item);
return root;
}
}
and then the recursive one is:
public void insert(T item) {
root = recInsert(root, item);
}
public BinaryTreeNode<T> recInsert(BinaryTreeNode<T> tree, T item) {
if(tree == null) {
//create new node
tree = new BinaryTreeNode<T>(item);
}
else {
Comparable<T> temp = (Comparable<T>) tree.info;
if (temp.compareTo(item) == 0) {
System.err.print("Already in ­ duplicates are not allowed.");
return null;
}
else if (temp.compareTo(item) > 0)
tree.lLink = recInsert(tree.lLink, item);
else
tree.rLink = recInsert(tree.rLink, item);
}
return tree;
}
does anyone know what I am doing wrong?
I thought I had gotten it but now it only returns the first number I enter in
here you go then
in your code,
if(current == null){
current.lLink=node;
if current is null, then how can it have a iLink ?
maybe you need to do
if(current == null){
current = new Node ();
current.lLink=node;
Your code is not even close to finish.
You haven't even done one comparison. What you did is simply meaningless loops.
If you are looking for a non-recursive logic, here is the pseudo code. Your job is to understand it and write it in Java.
insert(item) {
Node itemNode = new Node(item);
if root is null {
root = itemNode
return
}
currentNode = root;
keep looping until node is inserted {
if currentNode is equals to itemNode {
show error and exit
} else if itemNode is smaller than currentNode {
if (currentNode has no left){
set currentNode's left to itemNode
// Item Inserted!!!!
} else { // there are node at currentNode's left
set currentNode to currentNode's left (and continue lookup)
}
} else { // item node is greater than current node
// do similar thing as the "itemNode < currentNode logic",
// of course on currentNode's right
}
}
}

Why don't LinkedList's removeAll() and removeFirstOccurrence() remove the node?

I have to write code of these method. It is a homework, mustn't change the methods' params, or write an other method.
The contains() and isEmpty() work correctly. The removeFirst() and removerLast() work well too.
The removeFirstOccurence() doesn't remove the first ouccurence of specified element.
And the removeAll() doesn't revove the all of specified element.
/**
* Removes the first occurrence of the specified element in this list (when
* traversing the list from head to tail). *
* #param value element to be removed from this list, if present
* #return {#code true} if the list contained the specified element
*/
public boolean removeFirstOccurrence(int value) {
if(!contains(value))
return false;
else{
boolean result = false;
Node current = head;
while ((current != null) && !result) {
if (current.value == value){
current=current.next;
size--;
return true;
}
current = current.next;
}
return result;
}
}
/**
* Removes all occurrences of the specified element from this list.
* #param value the element to remove
* #return {#code false} if nothing changed, otherwise {#code true}
*/
public boolean removeAll(int value) {
if(isEmpty())
return false;
else{
boolean result = false;
Node current = head;
while ((current.next != null) && !result) {
if (current.value == value){
current=current.next;
size--;
result=true;
}
current= current.next;
}
return result;
}
}
Here the first part of MyLinkedList class:
public class MyLinkedList {
private class Node {
private int value;
private Node next;
private Node(int value) {
this.value = value;
this.next = null;
}
#Override
public String toString() {
...
}
}
private Node head;
private int size;
// and the methods...
you never alter any of the nodes in any way
public boolean removeFirstOccurrence(int value) {
//don't do contains(), you are looping over the entire thing anyway doing it again is useless
if(head==null)return false;
if(head.value==value){//does head contain the value
head=head.next;
size--;
return true;
}
Node prev = head;
while ((prev.next != null)) {//actually checking prev.next if it contains the value
if (prev.next.value == value){
prev.next=prev.next.next; //remove link from prev to prev.next
size--;
return true;
}
prev = prev.next;
}
return false;
}
public boolean removeAll(int value) {
if(head==null)return false;
while(head.value==value){//does head contain the value
head=head.next;
size--;
result=true;
}
Node prev=head;
while ((prev.next != null)) {//actually checking prev.next if it contains the value
(prev.next.value == value){
prev.next=prev.next.next; //remove link from prev to prev.next
size--;
result = true;
}else {
prev = prev.next;
}
}
return result;
}

Categories

Resources