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
}
Related
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
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;
}
}
folks, I've implemented the code for counting the total number of Nodes in a binary tree and the method looks like the following:
public int countNodes(Node root){
int count = 0;
if(root == null){
System.out.println("The tree is empty!");
return -1;
}
else{
count = 1;
Node current = root;
if(current.leftChild != null){
count += countNodes(current.leftChild);
}
else if(current.rightChild != null){
count += countNodes(current.rightChild);
}
}
System.out.print("The total number of nodes in the tree is ");
return count;
}
The parameter of the method contains Node root but my question is when I try to run the method from the main class then what should I pass as a parameter??
what should I add inside the parameters here?:
int countNodes = tree1.countNodes("?????????????");
package BST;
public class Node {
int data;
Node leftChild;
Node rightChild;
public void displayNode(){
System.out.println("The data is " + this.data);
}
}
class Tree{
private Node root;
public Tree(){
this.root = null;
}
public Node find(int key){
Node current = root;
while(current.data != key){
if(key < current.data){
current = root.leftChild;
}
else{
current = root.rightChild;
}
if(current == null){
System.out.println("The Node contatining the key " + key + " does not exist!");
return null;
}
}
return current;
}
public void insert(int key){
Node newNode = new Node();
if(root == null){
root = newNode;
}
else{
Node current = root;
Node parent;
while(true){
parent = current;
if(current.data > key){
current = current.leftChild;
if(current == null){
parent.leftChild = newNode;
return;
}
}
else{
current = current.rightChild;
if(current == null){
parent.rightChild = newNode;
return;
}
}
}
}
}
public Node findMin(){
if(root == null){
System.out.println("The tree is empty!");
return null;
}
else{
Node current = root.leftChild;
Node last = root;
while(current != null){
last = current;
current = current.leftChild;
}
return last;
}
}
public Node findMax(){
if(root == null){
System.out.println("The tree is empty!");
return null;
}
else{
Node current = root.rightChild;
Node last = root;
while(current != null){
last = current;
current = current.rightChild;
}
return last;
}
}
public int countNodes(Node root){
int count = 0;
if(root == null){
System.out.println("The tree is empty!");
return -1;
}
else{
count = 1;
Node current = root;
if(current.leftChild != null){
count += countNodes(current.leftChild);
}
else if(current.rightChild != null){
count += countNodes(current.rightChild);
}
}
System.out.print("The total number of nodes in the tree is ");
return count;
}
Class MainTester
class MainTester{
public static void main(String[] args){
Tree tree1 = new Tree();
tree1.insert(1);
tree1.insert(2);
tree1.insert(3);
tree1.insert(4);
tree1.insert(5);
tree1.insert(6);
tree1.insert(7);
tree1.insert(8);
tree1.insert(9);
tree1.insert(10);
int countNodes = tree1.countNodes("?????????????");
}
}
You can use the root node of the tree. Basing from your example, you can get it from the method find()
int countNodes = tree1.countNodes(tree1.find(1));
You can also use other nodes like
int countNodes = tree1.countNodes(tree1.find(5));
So i have 3 methods 1 that adds a node to the binary tree using the traverseAdd method, and another method which finds the location of where a value would be placed within the tree based on its parent node. I would like to eliminate the traverseAdd method and use the findLocation method within the add method to add the new value to the BST.
public void add(int val) {
/*Adds a new node to the binary tree after traversing the tree and figuring out where it belongs*/
Node nodeObjToAdd = new Node(val);
if(root == null){
//if node root is not null root = new node value
root = nodeObjToAdd;
}
Node nodeTraversed = root;
traverseAdd(nodeTraversed, nodeObjToAdd);
}
private void traverseAdd(Node node, Node nodeObjToAdd){
/*Traverses tree and finds a place to add the node to be added by comparing values of the left child and right child of the
* focus node*/
if(nodeObjToAdd.value < node.value){
if(node.leftChild == null){
node.leftChild = nodeObjToAdd;
}
else {
//if the val < the root.value set int he constructor
traverseAdd(node.leftChild, nodeObjToAdd);
}
}
else if(nodeObjToAdd.value > node.value) {
if (node.rightChild == null) {
node.rightChild = nodeObjToAdd;
} else {
traverseAdd(node.rightChild, nodeObjToAdd);
}
}
}
public Node findNodeLocation(Node rootNode, int val) {
/*returns where a the Node after which the value would be added.*/
if(val < rootNode.value && rootNode.leftChild != null){
return rootNode.leftChild;
}
if(val >= rootNode.value && rootNode.rightChild != null){
return rootNode.rightChild;
}
else
return this.root;
}
public void add(int val) {
if (root == null) {
root = new Node(val);
}
Node cur = root;
Node next = null;
while (true) {
next = findNodeLocation(cur, val);
if (next != cur) {
cur = next;
} else {
break;
}
}
if (val < cur.value) {
cur.leftChild = new Node(val);
} else {
cur.rightChild = new Node(val);
}
}
I think this should work
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;
}
}