Java AVL tree pointer manipulation - java

I'm having trouble implementing an AVL tree in java and would appreciate your help,
preferably by explaining what's wrong with my code (I've seen different implementations and would like to figure out what's wrong with mine).
public class AVLTree<T> {
public AVLNode<T> root;
int size;
//constructor
public AVLTree() {
root = null;
size = 0;
}
public void add(T obj) {
//initialize the new node
AVLNode<T> node = new AVLNode<T>(obj);
//if the tree is empty than our new node will serve as a root
if(root == null)
{
root = node;
size++;
return;
}
add(root, node);
}
private void checkViolations(AVLNode<T> node) {
int dif = Math.abs(height(node.left) - height(node.right)) ;
//there's a violation at our level
if(dif > 1)
{
rebalance(node);
}
//if we're at the root, tree is balances(AVL)
if(node.parent == null) return;
//we're not at the top, check parent
checkViolations(node.parent);
}
private void rebalance(AVLNode<T> node) {
//right subtree is bigger than left subtree
if(height(node.right) - height(node.left) > 1)
{
//problem is right-right
if(height(node.right.right) > height(node.right.left))
node = leftRotation(node);
//problem is right-left
else
node = rightLeftRotation(node);
}
//left subtree is bigger than right subtree
else
{
//problem is left-left
if (height(node.left.left) > height(node.left.right))
node = rightRotation(node);
//problem is left-right
else
node = leftRightRotation(node);
}
if (node.parent == null)
root = node;
}
private AVLNode<T> rightLeftRotation(AVLNode<T> node) {
node.right = rightRotation(node.right);
return leftRotation(node);
}
private AVLNode<T> leftRightRotation(AVLNode<T> node){
node.left = leftRotation(node.left);
return rightRotation(node);
}
private AVLNode<T> rightRotation(AVLNode<T> node) {
AVLNode<T> temp = node.left;
node.left = temp.right;
temp.parent = node.parent;
temp.right = node;
node.parent = temp;
return temp;
}
private AVLNode<T> leftRotation(AVLNode<T> node) {
AVLNode<T> temp = node.right;
node.right = temp.left;
temp.parent = node.parent;
temp.left = node;
node.parent = temp;
return temp;
}
private int height(AVLNode<T> node) {
//base case
if(node == null) return 0;
return 1 + (Math.max(height(node.left), height(node.right)));
}
private void add(AVLNode<T> parent, AVLNode<T> newNode) {
if(((Comparable<T>)newNode.data).compareTo(parent.data) > 0)
{
if(parent.right == null)
{
parent.right = newNode;
newNode.parent = parent;
size++;
}
else add(parent.right, newNode);
}
else
{
if(parent.left == null)
{
parent.left = newNode;
newNode.parent = parent;
size++;
}
else add(parent.left, newNode);
}
checkViolations(newNode);
}
}
I'm trying to add the next numbers in this order (left to right): 1,2,3,4,5
up until 4, everything seems to go great.
Thank you

Related

Whats wrong in this BST implementation?

Why am I getting false while doing search(7)?
I tried recursive solution its working fine..
tried implementing with loop failed
public class BST {
class Node {
int data;
Node left , right;
public Node(int data) {
this.data = data;
this.left = this.right = null;
}
}
Node root;
public BST() {
this.root = null;
}
public void insert(int data) {
// create a new node and start iteration from root node
Node newNode = new Node(data);
Node currentNode = this.root;
while (true) {
if (currentNode == null) {
currentNode = newNode;
break;
}
if (data < currentNode.data) { // if data is less go left
currentNode = currentNode.left;
} else if (data > currentNode.data) { // if data is greater go right
currentNode = currentNode.right;
} else { // do nothing for duplicates
break;
}
}
}
public boolean search(int data) {
Node currentNode = this.root;
while (true) {
if (currentNode == null) {
return false;
}
if (data == currentNode.data) {
return true;
} else if (data < currentNode.data) {
currentNode = currentNode.left;
} else {
currentNode = currentNode.right;
}
}
}
public static void main(String... args) {
BST tree = new BST();
tree.insert(15);
tree.insert(7);
System.out.println(tree.search(7));
}
}
Problem is inside the insert method - you are not inserting the nodes correctly inside the tree.
If the tree is empty, you should assign to this.root, not currentNode. Assigning to currentNode has no affect on this.root.
Currently, your code isn't inserting any node inside the tree; it simply assigns the new node to the local variable of insert method, i.e. currentNode.
If the condition data < currentNode.data is true, then you need to check if the currentNode.left is null or not. If it is, then link the new node with the current node as shown below:
currentNode.left = newNode;
If currentNode.left is not null, then do the following:
currentNode = currentNode.left;
Currently, your code moves the currentNode to null and then assigns the newNode to the currentNode without a reference to its parent node in the tree.
Do step 2 for data > currentNode.data as well.
Change the implementation of the insert method as shown below:
public void insert(int data) {
Node newNode = new Node(data);
if (this.root == null) {
this.root = newNode;
return;
}
Node currentNode = this.root;
while (true) {
if (data < currentNode.data) {
if (currentNode.left == null) {
currentNode.left = newNode;
} else {
currentNode = currentNode.left;
}
} else if (data > currentNode.data) {
if (currentNode.right == null) {
currentNode.right = newNode;
} else {
currentNode = currentNode.right;
}
} else {
break;
}
}
}

AVL Tree Data Strutcher in Java

I have written a Code for AVL Tree Insertion but when I try to print the value of Root Node it always returns Null. I am unable to understand the reason.Anyone who can solve this problem? I have tried many times but I could not resolve the problem. I am confused. I hope that someone from here will help in the case of resolving the problem I have as I am sure there are high level of experts here.
public class AVLTreeMethods {
public Node root = null;
public int height(Node node){
if (node == null)
return 0;
return node.height;
}
public int max(Node node1, Node node2){
if (node1.height > node2.height)
return node1.height;
return node2.height;
}
public Node rotateRight(Node node){
Node newNode = node.left;
node.left = newNode.right;
newNode.right = node;
node.height = max(node.left,node.right) + 1;
newNode.height = max(newNode.left, newNode.right) + 1;
return newNode;
}
public Node rotateleft(Node node){
Node newNode = node.right;
node.right = newNode.left;
newNode.left = node;
node.height = max(node.left,node.right) + 1;
newNode.height = max(newNode.left, newNode.right) + 1;
return newNode;
}
public Node AVLINSERT(int data, Node root){
if (root == null){
return new Node(data);
}
else if (data > root.data){
root.left = AVLINSERT(data, root.left);
}
else if (data < root.data){
root.right = AVLINSERT(data, root.right);
}
int balance = height(root.left) - height(root.right);
if (balance > 1){
if (height(root.left.left) > height(root.left.right)){
return rotateRight(root);
}
else {
root.left = rotateleft(root.left);
return rotateRight(root);
}
}
if (balance < -1){
if (height(root.right.right) > height(root.right.left)){
return rotateleft(root);
}
else
root.right = rotateRight(root);
return rotateleft(root);
}
root.height = 1 + max(root.left, root.right);
return root;
}
public void inorderPrinting(Node root){
inorderPrinting(root.left);
System.out.println(root.data);
inorderPrinting(root.right);
}
public void callingAVLInserting(int data){
AVLINSERT(data,root);
}
public void callinInorderPrinting(){
inorderPrinting(root);
}
}
Just by looking at your code, you have initialised the root to null however, you do not have any constructor that initializes it.
So try add something of the sort.
public class AVLTreeMethods {
public Node root = null;
//add the following
public AVLTreeMethods() {
//initialize your root appropriately e.g.
this.root = new Node(//pass in some data e.g 0)
}
...rest of your code
}

Finding the oldest element in a min priority queue java

I am supposed to return the oldest element in a priority min queue along with said element. I have to use nodes, arrays are optional. This is what I got so far but I have an null pointer error on line 20 and i don't know how to fix it. Please help
public class MinHeap {
public static int timeStamp = 0;
public static int ts = 0;
public static int maxTime = 0;
public static Node root;
public MinHeap(){
this.root = null;
}
public static void insert(int id, int ts){
timeStamp++;
Node newNode = new Node(id);
if(root==null){
root = newNode;
}
Node current = root;
Node parent = null;
while(true){
parent = current;
if(id < current.data){
current = current.left;
if(current==null){
parent.left = newNode;
}
}else{
current = current.right;
if(current==null){
parent.right = newNode;
}
}
}
}
public static Node delete(int x, Node n){
timeStamp++;
if(n==null)
return n;
if(x == n.data){
if(n.left == null && n.right == null){
return null;
}else if(n.left == null){
n.right = delete(x, n.right);
return n;
}else if(n.right == null){
n.left = delete(x, n.left);
return n;
}else{
Node tempNode = findMin(n.right);
n.right = delete(tempNode.data, n.right);
n.data = tempNode.data;
return n;
}
}
if(x < n.data){
n.left = delete(x, n.left);
return n;
}else{
n.right = delete(x, n.right);
return n;
}
}
public static void display(Node root){
if(root!=null){
display(root.left);
System.out.print(" " + root.data);
display(root.right);
}
}
public static Node findMin(Node n){
if(n == null){
return null;
}
if(n.left == null){
return n;
}
return findMin(n.left);
}
public static int maxAge(){
int currentAge = 0;
currentAge = timeStamp - ts;
if(currentAge > maxTime)
maxTime = currentAge;
return maxTime;
}
public static void main(String [] arg){
MinHeap min = new MinHeap();
min.insert(1, ts = 0);
min.insert(2, ts = 1);
min.insert(3, ts = 2);
min.insert(4, ts = 4);
min.delete(1, root);
min.delete(2, root);
min.delete(3, root);
min.delete(4, root);
min.maxAge();
}
}
class Node{
int data;
Node left;
Node right;
public Node(int data){
this.data = data;
left = null;
right = null;
}
}
Your insert is broken. You forgot to break after finding the insert point, and you're not checking for the case where the key is already in the tree.
while (true) {
parent = current;
if (id < current.data) {
current = current.left;
if (current == null) {
parent.left = newNode;
// Break after insert
break;
}
} else if (id > current.data) {
current = current.right;
if (current == null) {
parent.right = newNode;
// Break after insert
break;
}
} else {
// Key exists.
break;
}
}

Creating minimum binary search tree ( BST ) in Java

I'm working on a binary search tree and try to write a method for creating minimum BST from an array values. However, it's not working successfully. Where I'm making mistake ? It should print values in ascending order using inOrderTraverseTree method. I keep some additional methods and can delete if may feel irrelevant.
I updated the code in question, but, I still need to get the root Node to call the inOrderTraversal (Node root) method.
BinaryTree.java
class Node {
int key;
Node leftChild;
Node rightChild;
Node(int key) {
this.key = key;
}
Node (){}
public String toString() {
return "\n"+key+" ";
}
}
public class BinaryTree {
Node root;
BinaryTree (){
root = null;
}
public void addNode(int key) {
Node newNode = new Node(key);
// If there is no root this becomes root
if (root == null) {
root = newNode;
}
else {
// Set root as the Node we will start
// with as we traverse the tree
Node focusNode = root;
Node parent;
while (true) {
parent = focusNode;
if (key < focusNode.key) {
focusNode = focusNode.leftChild;
if (focusNode == null) {
parent.leftChild = newNode;
return; // All Done
}
} // end of if
else {
focusNode = focusNode.rightChild;
if (focusNode == null) {
parent.rightChild = newNode;
return;
}
}
}
}
}
// get the height of binary tree
public int height(Node root) {
if (root == null)
return -1;
Node focusNode = root;
int leftHeight = focusNode.leftChild != null ? height( focusNode.leftChild) : 0;
int rightHeight = focusNode.rightChild != null ? height( focusNode.rightChild) : 0;
return 1 + Math.max(leftHeight, rightHeight);
}
// METHODS FOR THE TREE TRAVERSAL
// inOrderTraverseTree : i) X.left ii) X iii) X.right
public void inOrderTraverseTree(Node focusNode) {
if (focusNode != null) {
inOrderTraverseTree(focusNode.leftChild);
// System.out.println(focusNode);
System.out.print( focusNode );
inOrderTraverseTree(focusNode.rightChild);
}
// System.out.println();
}
// preOrderTraverseTree : i) X ii) X.left iii) X.right
public void preorderTraverseTree(Node focusNode) {
if (focusNode != null) {
System.out.println(focusNode);
preorderTraverseTree(focusNode.leftChild);
preorderTraverseTree(focusNode.rightChild);
}
}
// postOrderTraverseTree : i) X.left ii) X.right iii) X
public void postOrderTraverseTree(Node focusNode) {
if (focusNode != null) {
preorderTraverseTree(focusNode.leftChild);
preorderTraverseTree(focusNode.rightChild);
System.out.println(focusNode);
}
}
// END
public Node findNode(int key) {
Node focusNode = root;
while (focusNode.key != key) {
if (key < focusNode.key) {
focusNode = focusNode.leftChild;
} else {
focusNode = focusNode.rightChild;
}
if (focusNode == null)
return null;
}
return focusNode;
}
public boolean remove(int key) {
Node focusNode = root;
Node parent = root;
boolean isItALeftChild = true;
// we will remove the focusNode
while (focusNode.key != key) {
parent = focusNode;
if (key < focusNode.key) {
isItALeftChild = true;
focusNode = focusNode.leftChild;
}
else {
isItALeftChild = false;
focusNode = focusNode.rightChild;
}
if (focusNode == null)
return false;
}
// no child
if (focusNode.leftChild == null && focusNode.rightChild == null) {
if (focusNode == root)
root = null;
else if (isItALeftChild)
parent.leftChild = null;
else
parent.rightChild = null;
}
// one child ( left child )
else if (focusNode.rightChild == null) {
if (focusNode == root)
root = focusNode.leftChild;
else if (isItALeftChild)
parent.leftChild = focusNode.leftChild;
else
parent.rightChild = focusNode.leftChild;
}
else if (focusNode.leftChild == null) {
if (focusNode == root)
root = focusNode.rightChild;
else if (isItALeftChild)
parent.leftChild = focusNode.rightChild;
else
parent.rightChild = focusNode.rightChild;
}
// two children exits
else {
// replacement is the smallest node in the right subtree
// we neeed to delete the focusNode
Node replacement = getReplacementNode(focusNode);
if (focusNode == root)
root = replacement;
else if (isItALeftChild)
parent.leftChild = replacement;
else
parent.rightChild = replacement;
replacement.leftChild = focusNode.leftChild;
}
return true;
}
public Node getReplacementNode(Node replacedNode) {
Node replacementParent = replacedNode;
Node replacement = replacedNode;
Node focusNode = replacedNode.rightChild;
// find the smallest node of the right subtree of the node to be deleted
while (focusNode != null) {
replacementParent = replacement;
replacement = focusNode;
focusNode = focusNode.leftChild;
}
// exit when the focusNode is null
// the replacement is the smallest of the right subtree
if (replacement != replacedNode.rightChild) {
replacementParent.leftChild = replacement.rightChild;
replacement.rightChild = replacedNode.rightChild;
}
return replacement;
}
private void createMinimalBST(int arr[], int start, int end, Node newNode){
if ( end <= start )
return;
int mid = (start + end) / 2;
newNode.key = arr[mid];
if ( root == null ){
root = newNode;
}
System.out.println("new node = "+ newNode );
if (start <= mid-1) {
newNode.leftChild = new Node();
createMinimalBST(arr, start, mid - 1, newNode.leftChild);
}
if (mid+1 <= end) {
newNode.rightChild = new Node();
createMinimalBST(arr, mid + 1, end, newNode.rightChild);
}
// System.out.println("left child = "+ newNode.leftChild +" "+ " right child = "+ newNode.rightChild);
}
public void createMinimalBST(int array[]) {
Node n = new Node();
createMinimalBST(array, 0, array.length - 1, n);
}
public static void main(String[] args) {
int[] myArr = { 1,2,3,4,5,6,7,8,9 }; // sortedArrayToBST
BinaryTree myTr = new BinaryTree();
// Node n = BinaryTree.createMinimalBST(myArr);
myTr.createMinimalBST(myArr);
// System.out.println("The root is = "+myTr.root);
// myTr.inOrderTraverseTree(myTr.root);
System.out.println();
myTr.inOrderTraverseTree(myTr.root);
}
}
You need to assign the result of createMinimalBST() to a variable.
This method returns a Node:
public Node createMinimalBST(int array[]) {...}
However, in the main, ...
myTr.createMinimalBST(myArr);
you calls to the method but no variable try to hold the result.
Also, You may want to make createMinialBST to be public static and call it like this:
myTr = BinaryTree.createMinimalBST(myArr);
Beside, there are 2 more ways to make this work:
1) move createMinimalBST() into Node, so that the recursion can occur while the key will be setting in-place.
private void createMinimalBST(int arr[], int start, int end){
int mid = (start + end) / 2;
this.key = arr[mid];
System.out.println("new node = "+n);
if (start <= mid-1) {
this.leftChild = new Node();
this.leftChild.createMinimalBST(arr, start, mid - 1);
}
if (mid+1 <= end) {
this.rightChild = new Node();
this.rightChild.createMinimalBST(arr, mid + 1, end);
}
System.out.println("left child = "+ newNode.leftChild +" "+ " right child = "+ newNode.rightChild);
}
2) If you want that method stays in BinaryTree, you can consider to pass in the Node as a parameter into createMinimalBST() ilke createMinimalBST(arr, node);
private void createMinimalBST(int arr[], int start, int end, Node newNode){
int mid = (start + end) / 2;
newNode.key = arr[mid];
System.out.println("new node = "+n);
if (start <= mid-1) {
newNode.leftChild = new Node();
createMinimalBST(arr, start, mid - 1, newNode.leftChild);
}
if (mid+1 <= end) {
newNode.rightChild = new Node();
createMinimalBST(arr, mid + 1, end, newNode.leftChild);
}
System.out.println("left child = "+ newNode.leftChild +" "+ " right child = "+ newNode.rightChild);
}

Recursive Binary Search Tree Deletion

Note: I've included the code for the insert in case that is where my error lies.
I'm having trouble removing nodes in my binary search tree. I ran this through eclipse and the node's "pointers" seem to be getting reassigned, but as soon as I exit my recursive method it goes back to the way the node was.
I may be misunderstanding how java is passing the tree nodes between methods.
public abstract class BinaryTree<E> implements Iterable<E> {
protected class Node<T> {
protected Node(T data) {
this.data = data;
}
protected T data;
protected Node<T> left;
protected Node<T> right;
}
public abstract void insert(E data);
public abstract void remove(E data);
public abstract boolean search(E data);
protected Node<E> root;
}
import java.util.Iterator;
public class BinarySearchTree<E extends Comparable<? super E>> extends BinaryTree<E> {
private Node<E> findIOP(Node<E> curr) {
curr = curr.left;
while (curr.right != null) {
curr = curr.right;
}
return curr;
}
public Iterator<E> iterator() {
return null;
}
public static void remove(E data) {
if (root != null){
if (data.compareTo(root.data) == 0) {
if (root.left == null || root.right == null) {
root = root.left != null ? root.left : root.right;
} else {
Node<E> iop = findIOP(root);
E temp = root.data;
root.data = iop.data;
iop.data = temp;
if (root.left == iop) {
root.left = root.left.left;
} else {
Node<E> curr = root.left;
while (curr.right != iop) {
curr = curr.right;
}
curr.right = curr.right.left;
}
}
} else {
if (data.compareTo(root.data) < 0) {
remove(root.left ,data);
} else {
remove(root.right ,data);
}
}
}
}
private void remove (Node<E> node, E data){
if (data.compareTo(node.data) == 0) {
if (node.left == null || node.right == null) {
if (node.left != null) {
// Problem is either here
node = node.left;
} else {
// or here
node = node.right;
}
} else {
Node<E> iop = findIOP(node);
E temp = node.data;
node.data = iop.data;
iop.data = temp;
if (node.left == iop) {
node.left = node.left.left;
} else {
Node<E> curr = node.left;
while (curr.right != iop) {
curr = curr.right;
}
curr.right = curr.right.left;
}
}
} else {
if (data.compareTo(node.data) < 0) {
remove(node.left ,data);
} else {
remove(node.right ,data);
}
}
}
}
When I insert:
tree.insert(10);
tree.insert(15);
tree.insert(6);
tree.insert(8);
tree.insert(9);
and then
tree.remove(8);
System.out.println(tree.root.left.right.data);
is still 8 instead of 9.
Removal works at the root and pointers are properly reassigned if removing from
root.left and root.right.
Any suggestion would be appreciated.
EDIT: I seem to have narrowed down the question. I implemented an iterative version where I make root = curr and change curr.left.right = curr.left.right.right. I notice that this change reflects my root node while when I pass node = root.left.right to my recursive function changing node to node.right does not reflect the changes in the root. Why is this?
Narrowed down some more. Why does node.left = node.left.left make changes to my tree and node = node.left do nothing.
I fixed it by recursively reassigning nodes of the parent as opposed to recursively reassigning the nodes in the child. This is the resulting private and public function.
public void remove(E data) {
Node<E> curr;
if (root != null) {
if (data.compareTo(root.data) == 0) {
if (root.left == null || root.right == null) {
root = root.left != null ? root.left : root.right;
}
else {
Node<E> iop = findIOP(root);
E temp = root.data;
root.data = iop.data;
iop.data = temp;
if (root.left == iop) {
root.left = root.left.left;
}
else {
curr = root.left;
while (curr.right != iop) {
curr = curr.right;
}
curr.right = curr.right.left;
}
}
} else if (data.compareTo(root.data) < 0) {
root.left = remove(data, root.left);
} else {
root.right = remove(data, root.right);
}
}
}
private Node<E> remove(E data, Node<E> node){
Node<E> curr;
if (node != null){
if (data.compareTo(node.data) == 0) {
if (node.left == null || node.right == null) {
node = node.left != null ? node.left : node.right;
return node;
} else {
Node<E> iop = findIOP(node);
E temp = node.data;
node.data = iop.data;
iop.data = temp;
if (node.left == iop) {
node.left = node.left.left;
return node;
} else {
curr = node.left;
while (curr.right != iop) {
curr = curr.right;
}
curr.right = curr.right.left;
return node;
}
}
} else {
if (data.compareTo(node.data) < 0) {
node.left = remove(data, node.left);
if (node.left != null){
return node.left;
}
} else {
node.right = remove(data, node.right);
if (node.right != null){
return node.right;
}
}
// if node.left/right not null
return node;
}
}
// if node = null;
return node;
}
You are indeed right when you say "I may be misunderstanding how java is passing the tree nodes between methods". Consider:
public class Ref {
public static void main(String args[]) {
Integer i = new Integer(4);
passByRef(i);
System.out.println(i); // Prints 4.
}
static void passByRef(Integer j) {
j = new Integer(5);
}
}
Although i is "passed by reference", the reference i itself isn't changed by the method, only the thing that j refers to. Put another way, j is initialized with a copy of the reference i, that is, j initially refers to the same object as i (but crucially is not i). Assigning j to refer to something else has no effect on what i refers to.
To achieve what you want in your search, I suggest you instead return the new reference to the caller. For example, something analogous to the following change:
public class Ref {
public static void main(String args[]) {
Integer i = new Integer(4);
i = passByRef(i);
System.out.println(i); // Prints 5.
}
static Integer passByRef(Integer j) {
j = new Integer(5);
return j;
}
}

Categories