- /**
- * filename: AVLNode.java
- * package:
- * author: Nick Ma
- * email: nick.ma85@yahoo.com
- * date: Nov 12, 2008
- * description: this class implements the node of avl tree.
- */
- public class AVLNode<T extends Comparable<T>> extends BinaryNode<T> {
- // Data Field
- /** the parent node of this current node */
- private AVLNode<T> parent;
- /** the height of this current node */
- private int height;
- /**
- * description: the constructor to initialize the data
- * @param data - the data in the node
- */
- public AVLNode(T data) {
- super (data);
- // TODO Auto-generated constructor stub
- this .height = 0 ;
- this .parent = null ;
- }
- /**
- * description: the constructor with fields
- * @param data - the data in the node
- * @param left - left child of this node
- * @param right - right child of this node
- */
- public AVLNode(T data, AVLNode<T> left, AVLNode<T> right) {
- super (data, left, right);
- this .height = 0 ;
- this .parent = null ;
- }
- /**
- * description: the constructor to convert this node from a binary node
- * @param node - the binary node
- */
- public AVLNode(BinaryNode<T> node) {
- super (node.data, node.left, node.right);
- this .height = 0 ;
- this .parent = null ;
- }
- /**
- * @return the height
- */
- public int getHeight() {
- return height;
- }
- /**
- * @param height the height to set
- */
- public void setHeight( int height) {
- this .height = height;
- }
- /**
- * @return the parent
- */
- public AVLNode<T> getParent() {
- return parent;
- }
- /**
- * @param parent the parent to set
- */
- public void setParent(AVLNode<T> parent) {
- this .parent = parent;
- }
- /* (non-Javadoc)
- * @see LiMaHW4.BinaryNode#getLeft()
- */
- public AVLNode<T> getLeft() {
- // TODO Auto-generated method stub
- return (AVLNode<T>) super .getLeft();
- }
- /* (non-Javadoc)
- * @see LiMaHW4.BinaryNode#getRight()
- */
- public AVLNode<T> getRight() {
- // TODO Auto-generated method stub
- return (AVLNode<T>) super .getRight();
- }
- }
- /**
- * filename: AVLTree.java
- * package:
- * author: Nick Ma
- * email: nick.ma85@yahoo.com
- * date: Nov 12, 2008
- * description: this class implements an avl tree.
- */
- public class AVLTree<T extends Comparable<T>> extends BinarySearchTree<T> {
- // Data Field
- /**
- * description: insert a node into the tree
- * @param item - the data of the node
- * @return - the node inserted
- */
- public AVLNode<T> insert(T item) {
- // check if the data is valid
- if (item == null ) {
- return null ;
- }
- // create a new node to store the data
- AVLNode<T> newNode = new AVLNode<T>(item);
- // add this node to the tree
- this .add(newNode);
- // reset the height of the inserted node
- this .setHeight(newNode);
- // rebalance the tree after insertion
- this .rebalance(newNode);
- // return the node inserted
- return newNode;
- }
- /**
- * description: remove a node from the tree
- * @param item - the data in the removed node
- * @return - true if the node is removed
- */
- public boolean remove(T item) {
- // delete the node with the data from the tree
- super .delete(item);
- if ( this .deletedNode == null ) {
- return false ;
- }
- // get the reference of the deleted node
- AVLNode<T> node = (AVLNode<T>) this .deletedNode;
- while (! super .isRoot(node)) {
- // reference to its parent
- node = node.getParent();
- // reset the height
- this .setHeight(node);
- // rebalance the subtree whose root is node
- this .rebalance(node);
- }
- return true ;
- }
- /**
- * description: display this tree by in-order traversal
- */
- public void display() {
- StringBuilder sb = new StringBuilder();
- super .inOrderTraverse(root, 0 , sb);
- System.out.println(sb.toString());
- }
- /**
- * description: add new node in the tree
- * @param newNode - the new node
- */
- public void add(AVLNode<T> newNode) {
- this .root = this .addAux((AVLNode<T>) this .root, newNode);
- if (newNode == this .root) {
- newNode.setParent( null );
- }
- }
- /**
- * description: recursive add-auxiliary method
- * @param node - the local root
- * @param newNode - the new node
- * @return - the new local root which contains the new node
- */
- private AVLNode<T> addAux(AVLNode<T> node, AVLNode<T> newNode) {
- if (node == null ) {
- // the tree is empty
- return newNode;
- } else {
- int result = newNode.getData().compareTo(node.getData());
- if (result < 0 ) {
- // insert new node in the left subtree
- node.setLeft(addAux(node.getLeft(), newNode));
- node.getLeft().setParent(node);
- } else if (result > 0 ){
- // insert new node in the right subtree
- node.setRight(addAux(node.getRight(), newNode));
- node.getRight().setParent(node);
- }
- return node;
- }
- }
- /**
- * description: delete the node in the tree
- * @param data - the data of the deleted node
- * @return - the deleted node
- */
- public AVLNode<T> delete(T data) {
- this .root = this .deleteAux((AVLNode<T>) this .root, data);
- ((AVLNode<T>) this .root).setParent( null );
- return (AVLNode<T>) this .deletedNode;
- }
- /**
- * description: recursive delete-auxiliary method
- * @param node - the local root
- * @param target - the data of the deleted node
- * @return - the new local root which deletes the target node
- */
- private AVLNode<T> deleteAux(AVLNode<T> node, T target) {
- if (node == null ) {
- // the tree is empty
- return null ;
- } else {
- int result = target.compareTo(node.getData());
- if (result < 0 ) {
- // target is less than the data in the local root
- node.setLeft(deleteAux(node.getLeft(), target));
- node.getLeft().setParent(node);
- return node;
- } else if (result > 0 ){
- // target is greater than the data in the local root
- node.setRight(deleteAux(node.getRight(), target));
- node.getLeft().setParent(node);
- return node;
- } else {
- // target is equal to the data in the local root
- deletedNode = node;
- if (node.getLeft() == null ) {
- // there's no left child in the local root
- return node.getRight();
- } else if (node.getRight() == null ) {
- // there's no right child in the local root
- return node.getLeft();
- } else {
- // the local root has two children
- if (node.getLeft().getRight() == null ) {
- node.setData(node.getLeft().getData());
- node.setLeft(node.getLeft().getLeft());
- node.getLeft().setParent(node);
- } else {
- node.setData( super .findLargestChild(node.getLeft()));
- }
- return node;
- }
- }
- }
- }
- // Rotations for AVL Tree
- /**
- * description: rotate the avl tree to right
- * @param node - the unbalanced local root
- * @return - the balanced local root
- */
- private AVLNode<T> rotateR(AVLNode<T> node) {
- // check if the node is valid
- if (node == null || node.getLeft() == null ) {
- return null ;
- }
- AVLNode<T> newNode = (AVLNode<T>)node.getLeft();
- node.setLeft(newNode.getRight());
- newNode.setRight(node);
- // reset the parent node of the nodes just modified
- node.setParent(newNode);
- if (node.getLeft() != null ) {
- node.getLeft().setParent(node);
- }
- // reset the height of the nodes just modified
- this .setHeight(node);
- this .setHeight(newNode);
- // if root is changed, newNode must be the new root
- if ( super .isRoot(node)) {
- newNode.setParent( null );
- this .root = newNode;
- }
- return newNode;
- }
- /**
- * description: rotate the avl tree to left
- * @param node - the unbalanced local root
- * @return - the balanced local root
- */
- private AVLNode<T> rotateL(AVLNode<T> node) {
- // check if the node is valid
- if (node == null || node.getRight() == null ) {
- return null ;
- }
- AVLNode<T> newNode = (AVLNode<T>)node.getRight();
- node.setRight(newNode.getLeft());
- newNode.setLeft(node);
- // reset the parent node of the nodes just modified
- node.setParent(newNode);
- if (node.getRight() != null ) {
- node.getRight().setParent(node);
- }
- // reset the height of the nodes which is just modified
- this .setHeight(node);
- this .setHeight(newNode);
- // if root is changed, newNode must be the new root
- if ( super .isRoot(node)) {
- newNode.setParent( null );
- this .root = newNode;
- }
- return newNode;
- }
- /**
- * description: doublely rotate the avl tree to left
- * @param node - the unbalanced local root
- * @return - the balanced local root
- */
- private AVLNode<T> rotateRL(AVLNode<T> node) {
- // check if the node is valid
- // that is, the node has a right child
- // and its right child has a left child
- if (node == null || node.getRight() == null
- || node.getRight().getLeft() == null ) {
- return null ;
- }
- node.setRight( this .rotateR(node.getRight()));
- node.getRight().setParent(node);
- return this .rotateL(node);
- }
- /**
- * description: doublely rotate the avl tree to right
- * @param node - the unbalanced local root
- * @return - the balanced local root
- */
- private AVLNode<T> rotateLR(AVLNode<T> node) {
- // check if the node is valid
- // that is, the node has a left child
- // and its left child has a right child
- if (node == null || node.getLeft() == null
- || node.getLeft().getRight() == null ) {
- return null ;
- }
- node.setLeft( this .rotateL(node.getLeft()));
- node.getLeft().setParent(node);
- return this .rotateR(node);
- }
- // End of Rotations for AVL Tree
- /**
- * description: rebalance the local root
- * @param node - the local root
- */
- private void rebalance(AVLNode<T> node) {
- if (node == null ) {
- return ;
- }
- AVLNode<T> newNode = null ; // the balanced root
- // check if the local root isn't the root node of the tree
- while (! super .isRoot(node)) {
- // reference to its parent
- node = node.getParent();
- // reset the height
- this .setHeight(node);
- if (! this .isBalanced(node)) {
- // if unbalanced
- AVLNode<T> y = this .tallerChild(node);
- AVLNode<T> x = this .tallerChild(y);
- AVLNode<T> p = node.getParent();
- // rotate the subtree
- if (y == node.getLeft() && x == y.getLeft()) {
- newNode = this .rotateR(node);
- } else if (y == node.getLeft() && x == y.getRight()) {
- newNode = this .rotateLR(node);
- } else if (y == node.getRight() && x == y.getLeft()) {
- newNode = this .rotateRL(node);
- } else if (y == node.getRight() && x == y.getRight()) {
- newNode = this .rotateL(node);
- }
- if (p != null && ! super .isRoot(p)) {
- if (node == p.getLeft()) {
- p.setLeft(newNode);
- p.getLeft().setParent(p);
- } else if (node == p.getRight()) {
- p.setRight(newNode);
- p.getRight().setParent(p);
- }
- }
- return ;
- }
- }
- }
- /**
- * description: determine if the local root is balanced or not
- * @param node - the local root
- * @return - true if the local root is balanced
- */
- private boolean isBalanced(AVLNode<T> node) {
- if (node == null ) {
- return true ;
- } else if (node.getLeft() == null && node.getRight() == null ) {
- return true ;
- } else if (node.getLeft() != null && node.getRight() == null ) {
- // the height of the left subtree is -1
- return node.getLeft().getHeight() + 1 <= 1 ;
- } else if (node.getLeft() == null && node.getRight() != null ) {
- // the height of the right child is -1
- return node.getRight().getHeight() + 1 <= 1 ;
- } else {
- return (Math.abs(node.getLeft().getHeight() - node.getRight().getHeight()) <= 1 );
- }
- }
- /**
- * description: set the height of the local root
- * @param node - the local root
- */
- private void setHeight(AVLNode<T> node) {
- if (node == null ) {
- return ;
- } else if (node.getLeft() == null && node.getRight() == null ) {
- node.setHeight( 0 );
- } else if (node.getLeft() == null && node.getRight() != null ) {
- node.setHeight(node.getRight().getHeight() + 1 );
- } else if (node.getLeft() != null && node.getRight() == null ) {
- node.setHeight(node.getLeft().getHeight() + 1 );
- } else {
- node.setHeight(Math.max(node.getLeft().getHeight(), node.getRight().getHeight()) + 1 );
- }
- }
- /**
- * description: get the taller child of the local root
- * @param node - the local root
- * @return - the taller child
- */
- private AVLNode<T> tallerChild(AVLNode<T> node) {
- if (node == null ) {
- return null ;
- } else if (node.getLeft() == null && node.getRight() == null ) {
- return null ;
- } else if (node.getLeft() == null && node.getRight() != null ) {
- return node.getRight();
- } else if (node.getLeft() != null && node.getRight() == null ) {
- return node.getLeft();
- } else {
- return (node.getLeft().getHeight() > node.getRight().getHeight()) ? node.getLeft() : node.getRight();
- }
- }
- }
AVL Tree
最新推荐文章于 2024-06-16 16:00:00 发布