Trying to construct an AVLTree

  • Thread starter STEMucator
  • Start date
In summary, the conversation is about constructing an AVLTree and the issues the person is facing in their code. They share their AVLTree class, which includes insert and delete methods, as well as the AVLTreeNode class which handles insertion. The person is trying to insert nodes 5, 3, and 1, but is experiencing unexpected behavior where the 3 and 1 nodes disappear and only the 5 node remains. They mention that the desired outcome should be a tree with 3 as the root, 1 as the left child, and 5 as the right child. They are seeking help in identifying the issue in their code.
  • #1
STEMucator
Homework Helper
2,076
140
So I'm trying to construct an AVLTree and something crazy seems to be happening in my code.

AVL Tree Class. This includes only the insert and delete methods, soon to be a find method as well :

Code:
package comp2402TreeEditor;

public class AVLTree extends BSTree {  
	
	public AVLTree() {}
	
    public void insert(String dataString){
	   	Data data = new Data(dataString);
	   	
	   	AVLTreeNode newChildNode = new AVLTreeNode(data);

	   	if(isEmpty()) {
	   		setRoot(newChildNode);
	   		newChildNode.setLocation(getOwner().getDefaultRootLocation());
	   	}
	   	
	   	else
	   		getRoot().insertNode(newChildNode);
    }
	
    public void remove(String aKeyString){
    	if(isEmpty()) return;
        
    	if(size()==1){
    		Data temp = new Data(aKeyString);
    		if(root().getData().compare(temp) == 0)
    			setRoot(null);
    		return;
        }
     
        getRoot().remove(aKeyString);   
    }
	
}

Now as for the real problem, here's my AVLTreeNode Class. I'm focusing mainly on the insertion portion right now :

Code:
package comp2402TreeEditor;

import java.awt.Point;

public class AVLTreeNode extends BSTreeNode{

	int balance;
	
	public AVLTreeNode() {}

	public AVLTreeNode(Point aPoint) {
		super(aPoint);
		balance = 0;
	}
	
	public AVLTreeNode(Data data) {
		super(data);
		balance = 0;
	}
	
	public void insertNode(TreeNode aNode) {
		if(!(aNode instanceof AVLTreeNode)) return;
		
		System.out.println(this);
		System.out.println(aNode);
		System.out.println(leftChild);
		System.out.println(rightChild);
		
		if(aNode.getData().compare(getData()) < 0) {
			if(leftChild == null) {
				leftChild = (AVLTreeNode) aNode;
		      	aNode.setParent(this);
	    		recursiveBalance(this);
		      	aNode.setLocation(this.getLocation()); //starting location for animation
			}
			else{
				leftChild.insertNode(aNode);
			}
		}
		
		else{
			if(rightChild == null) {
				rightChild = (AVLTreeNode) aNode;
	       	  	aNode.setParent(this);
	    		recursiveBalance(this);
	       	  	aNode.setLocation(this.getLocation()); //starting location for animation
			}
			else {
				rightChild.insertNode(aNode);
			}
		}
	}
	
	public void remove(String aDataString){			
		Data temp = new Data(aDataString);

		int comparision = temp.compare(this.getData());
			   
		if(comparision < 0 && leftChild != null) {
			leftChild.remove(aDataString);
		}
			   
		else if(comparision > 0 && rightChild != null) {
			rightChild.remove(aDataString);
		}
		
		else if(comparision == 0){
			//found a node to remove so remove this node
			if(isLeaf()) 
				getParent().removeChildNode(this);
			
			else if(isRoot() && rightChild == null) {
				//hijack the leftChild as the new root of the tree
				setData(leftChild.getData());
				leftChild.setParent(null);
				
				rightChild = (AVLTreeNode) leftChild.rightChild();
				if(rightChild != null) 
					rightChild.setParent(this);
				
				leftChild = (AVLTreeNode) leftChild.leftChild();
				if(leftChild != null) 
					leftChild.setParent(this);
			}
			
			else if(isRoot() && leftChild == null) {
				//hijack the right as the new root of the tree
				setData(rightChild.getData());
				rightChild.setParent(null);
				leftChild = (AVLTreeNode) rightChild.leftChild();
				if(leftChild != null) 
					leftChild.setParent(this);
				
				rightChild = (AVLTreeNode) rightChild.rightChild();
				if(rightChild != null) 
					rightChild.setParent(this);
			}
			
			else if(leftChild == null && rightChild != null) {
				//promote rightchild as new child of parent
				((AVLTreeNode) getParent()).replaceChildNode(this, rightChild);
			}
			else if(rightChild == null && leftChild != null) {
				//promote left child as new child of parent
				((AVLTreeNode) getParent()).replaceChildNode(this, leftChild);
			}
			else{
				//we need to remove an internal node with two current children
				//find the smallest next node via the right subtree and use it as a
				//replacement for this node
				
				TreeNode smallest = ((AVLTreeNode) rightChild).findSmallestNode();
				this.setData(smallest.getData()); //steel the data object of the smallest node
				smallest.remove(smallest.key());
				//System.out.println("BSTreeNode::remove: smallest to remove= " + smallest.key());
			}		
		}
	}
	
	public void recursiveBalance(AVLTreeNode current) {
		 setBalance(current);
		 int tBalance = current.balance;

		 System.out.println(current + " " + this);
		 System.out.println(tBalance);

		 if(tBalance == -2) {
			 if(height((AVLTreeNode)current.leftChild.leftChild) >= height((AVLTreeNode)current.leftChild.rightChild))
				 current = rotateRight(current);
			 else
				 current = doubleRotateLeftRight(current);
		 }  
		 if(tBalance == 2) {
			 if(height((AVLTreeNode)current.rightChild.rightChild) >= height((AVLTreeNode)current.rightChild.leftChild))
				 current = rotateLeft(current);
			 else
				 current = doubleRotateRightLeft(current);
		 }

		 if(current.getParent() != null) {
			 recursiveBalance((AVLTreeNode)current.getParent());
		 }
		 
		 else {
			 //Need to somehow set the root to be current RIGHT HERE!
			 System.out.println("Balancing Complete!");
		 }
	 }
	 
	 public AVLTreeNode rotateLeft(AVLTreeNode n) {
		 AVLTreeNode v = (AVLTreeNode)n.rightChild;
		 v.setParent(n.getParent());
		 n.rightChild = v.leftChild;
		 
		 if(n.rightChild != null)
			 n.rightChild.setParent(n);
	 
		  v.leftChild = n;
		  n.setParent(v);
	 
		  if(v.getParent() != null) {
			  if(((AVLTreeNode)v.getParent()).rightChild == n)
				  ((AVLTreeNode)v.getParent()).rightChild = v;
			  else if( ((AVLTreeNode)v.getParent()).leftChild == n)
				  ((AVLTreeNode)v.getParent()).leftChild = v;
		  }
	 
		  setBalance(n);
		  setBalance(v);
		  return v;
	 }
	 
	 public AVLTreeNode rotateRight(AVLTreeNode n) {
		 AVLTreeNode v = (AVLTreeNode)n.leftChild; //(3)
		 v.setParent(n.getParent()); //(null)
		 n.leftChild = v.rightChild; //(null)
		 
		 if(n.leftChild!=null)
			 n.leftChild.setParent(n);
	 
		  v.rightChild = n;
		  n.setParent(v);

		  if(v.getParent() != null) {
			  if(((AVLTreeNode)v.getParent()).rightChild == n)
				  ((AVLTreeNode)v.getParent()).rightChild = v;
			  else if( ((AVLTreeNode)v.getParent()).leftChild == n)
				  ((AVLTreeNode)v.getParent()).leftChild = v;
		  }
		  setBalance(n);
		  setBalance(v);
		  return v;
	 }

	 public AVLTreeNode doubleRotateLeftRight(AVLTreeNode u) {
		 u.leftChild = rotateLeft((AVLTreeNode)u.leftChild);
		 return rotateRight(u);
	 }

	 public AVLTreeNode doubleRotateRightLeft(AVLTreeNode u) {
		 u.rightChild = rotateRight((AVLTreeNode)u.rightChild);
		 return rotateLeft(u);
	 }

	 public AVLTreeNode successor(AVLTreeNode q) {
		 if(q.rightChild != null) {
			 AVLTreeNode r = (AVLTreeNode)q.rightChild;
			 while(r.leftChild != null)
				 r = (AVLTreeNode)r.leftChild;
			 return r;
		 } 
		  
		 else {
			 AVLTreeNode p = (AVLTreeNode)q.getParent();
			 while(p != null && q == p.rightChild) {
				 q = p;
				 p = (AVLTreeNode)q.getParent();
			 }
			 return p;
		 }
	 }

	 private int height(AVLTreeNode current) {
		 if(current == null)
			 return -1;
		 if(current.leftChild == null && current.rightChild == null)
			 return 0;
		 else if(current.leftChild == null)
			 return 1+height((AVLTreeNode)current.rightChild);
		 else if(current.rightChild == null)
			 return 1+height((AVLTreeNode)current.leftChild);
		 else
			 return 1+maximum(height((AVLTreeNode)current.leftChild),height((AVLTreeNode)current.rightChild));
	 }

	 private int maximum(int a, int b) {
		 return (a>=b) ? a : b;
	 }
	 
	 private void setBalance(AVLTreeNode current) {
		 current.balance = height((AVLTreeNode)current.rightChild) - height((AVLTreeNode)current.leftChild);
	 }
	 
	private void replaceChildNode(TreeNode currentChild, TreeNode newChild){
		//replace the currentChild of this node with the newChild node
		if(leftChild == currentChild){
			removeChildNode(currentChild);
			leftChild = (AVLTreeNode) newChild;
			newChild.setParent(this);
		}
		else if(rightChild == currentChild){
			removeChildNode(currentChild);
			rightChild = (AVLTreeNode) newChild;
			newChild.setParent(this);
		}
	}
	
	private TreeNode findSmallestNode(){
		//find the smallest node searching from this node along the left subtrees
		//in a binary search tree the node with the smallest key will be found by
		//going left as far as possible.
		
		if(leftChild == null) return this;
		else return ((AVLTreeNode) leftChild).findSmallestNode();
		
	}
}

Crazy things seem to happen when i try to create a tree by inserting 5, 3 and then 1. The 3 and 1 nodes disapear into nowhere and only the 5 node is left surviving ( which is absolutely incorrect ).

What should happen is that since 5 is my root, 3 is a left child and 1 is a left left child; I should see a re-arrangement of my tree to 3 1 5 where 3 is now the root, 1 is the left child and 5 is the right child.

For some reason this does not seem to be happening? If anyone can spot the kink please let me know as I've been at this for 3 days now and it's getting quite tiresome.

EDIT : Here's a picture of my gui and what's going on.

Picture of inserting 5 and then 3 : http://gyazo.com/6cf46d74404d5e49650a096b721f8b2a
Picture of inserting 1 right after : http://gyazo.com/2b04ee63e66991fbc93cc201fa981159
 
Physics news on Phys.org
  • #2
As you can see, the 1 node is missing and what should be a perfect balance of 3 5 1 is now just 5.Thanks again for any help!
 

1. What is an AVLTree and why is it important in computer science?

An AVLTree is a self-balancing binary search tree data structure. It is important in computer science because it maintains a balanced tree structure, which allows for efficient searching and inserting of data.

2. How do I construct an AVLTree?

To construct an AVLTree, you must first create a root node and then add subsequent nodes according to the AVLTree balancing rules. This includes performing rotations and updates to keep the tree balanced after each insertion.

3. What are the advantages of using an AVLTree over other data structures?

One advantage of using an AVLTree is its efficient time complexity for searching, inserting, and deleting data. It also guarantees a balanced tree structure, which can improve performance and reduce memory usage.

4. Are there any limitations to using an AVLTree?

One limitation of using an AVLTree is that the balancing operations can be more complex and time-consuming compared to other simpler data structures. Additionally, it may not be the best choice for all types of data, as certain patterns of data insertion can result in a poorly balanced tree.

5. How do I ensure that my AVLTree is properly constructed?

To ensure that your AVLTree is properly constructed, you can use various methods for traversing and visualizing the tree, such as in-order or level-order traversal. Additionally, you can perform tests to check for balanced tree properties and compare it to other known balanced tree structures.

Similar threads

  • Engineering and Comp Sci Homework Help
Replies
1
Views
9K
  • Programming and Computer Science
Replies
3
Views
2K
  • Programming and Computer Science
Replies
3
Views
3K
  • Engineering and Comp Sci Homework Help
Replies
5
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
18
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
3K
  • Engineering and Comp Sci Homework Help
Replies
1
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
6
Views
3K
  • Engineering and Comp Sci Homework Help
Replies
1
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
2K
Back
Top