190 likes | 315 Views
AVL Tree. Buat Class untuk : BST AVL AVLdemo AVLverbose. BST.java. import java.util .*; @ SuppressWarnings ("unchecked") public class BST { static class BSTnode { Comparable data; // Realistic case, this could be quite large
E N D
AVL Tree
Buat Class untuk : • BST • AVL • AVLdemo • AVLverbose
BST.java import java.util.*; @SuppressWarnings("unchecked") public class BST { static class BSTnode { Comparable data; // Realistic case, this could be quite large int height; // Height of THIS NODE int size; // Number of nodes in this (sub)tree intutil; // Generic utility area for an int value BSTnode left, // "<" subtree right; // ">" subtree BSTnode ( Comparable data ) // Constructor for leaf node { this.data = data; this.height = this.size = 1; this.left = null; this.right = null; } } protected BSTnode root = null, current = null; // Spare reference for processing private intnItems; // Used in the protected tree walk private BSTnode free = null; // nodes for re-use public int size() { return root == null ? 0 : root.size; }
public int height() // root = null means empty = 0 { return root == null ? 0 : root.height; } public double avgDepth() { if ( root == null ) return 0; else return sumDepths(root, 1) / root.size; } // end avgDepth() // Total all depths of nodes within the tree: double sumDepths(BSTnode node, int deep) { if (node == null) return 0; else return deep + sumDepths (node.left, deep+1) + sumDepths (node.right, deep+1); } // end sumDepths() Comparable find(Comparable value) { current = root; while ( current != null && !current.data.equals(value) ) { if (value.compareTo(current.data) < 0) current = current.left; else current = current.right; } return current == null ? null : current.data; }
public void clear() { autumn(root); root = null; } // All the leaf (nodes) fall . . . recursively void autumn (BSTnode node) { if ( node != null ) { autumn(node.left); // post-order traversal autumn(node.right); recycle(node); // This is now a leaf. Goodbye! } } // end autumn() public void insert(Comparable value) { root = insert(root, value); } // Recursive insertion, returning reference to subtree generated. BSTnode insert(BSTnode node, Comparable value) { if ( node == null ) node = new BSTnode (value); else if ( value.compareTo(node.data) < 0 ) node.left = insert (node.left, value); else if ( ! UNIQUE ) node.right = insert (node.right, value); // ***** Equal keys must be FORBIDDEN ***** else if ( value.compareTo(node.data) > 0 ) node.right = insert (node.right, value); // ***** If equal keys are NOT allowed, ERROR ***** else { System.err.println (value + " is already in."); } // end if/else if/else if/else if/else // Correct this node's height and size after the insertion. // The correction propagates upwards in the recursive call stack. node.height = newHt(node); node.size = newSize(node); return node; } // end insert(BSTnode, Comparable)
public void delete(Comparable value) { deleteNode = null; lastNode = null; root = delete(root, value); } static void swapData (BSTnode d, BSTnode s) { Comparable temp = d.data; d.data = s.data; s.data = temp; } BSTnode delete(BSTnode node, Comparable value) { if ( node == null ) return null; lastNode = node; // Reference to LAST node seen if ( value.compareTo(node.data) < 0 ) node.left = delete (node.left, value); else {//When we FIND the node and take one step right, all subsequent //steps will be left --- down to the in-order successor deleteNode = node; // Potentially the node to go node.right = delete (node.right, value); }
if ( node == lastNode ) {//Check to see if we indeed DID find the value if ( deleteNode != null && value.equals(deleteNode.data) ) {//Final check: if node is RIGHTMOST in its subtree if ( deleteNode == lastNode ) // Half-nodes are easy! { node = node.left; // Return left subtree } //node is NOT rightmost in its subtree. Copy replacement up. else { swapData (deleteNode, lastNode); node = node.right; // Return right subtree } recycle (lastNode); // Return the node for re-use } } else // Adjust heights on the way back up the recursive stack { node.height = newHt(node); node.size = newSize(node); } return node; } public void walk() { if (root != null) { nItems = 0; inOrder(root); // Check whether final '\n' is required. if (nItems % 10 != 0) System.out.println(); } } // end walk()
void inOrder(BSTnode item) { if ( item == null) return; // I.e., empty tree inOrder(item.left); // Process left sub-tree System.out.printf("%4s(%d)", item.data,item.height); if ( ++nItems % 10 == 0 ) System.out.println(); inOrder(item.right); // Process right sub-tree } static int skip; public void pretty() { skip = 0; if ( root == null ) // Nothing to display! { System.out.println ("Empty tree!"); return; } setPos (root); // Find line position for each node pretty (root); // level-order traversal displaying the nodes }
void setPos (BSTnode node) {//If the nodes were all printed on one line, their order is based // on an in-order traversal. skip shows number of positions to skip // to properly position the node. Note that this MUST be a class // data member --- the root depends on skip to come back with the // size of the entire left subtree, for instance. if ( node != null ) { setPos (node.left); node.util = skip; // Store skip value in util data member skip += 2; // Update for printing THIS node setPos (node.right); } // end if } // end setPos() // We need to retain information on tree level in a queue of BSTnodes. static class Wrapper { int level; BSTnode node; Wrapper(BSTnode node, int level) { this.level = level; this.node = node; } }
void pretty (BSTnode node) {//work queue during traversal Deque<Wrapper> queue = new ArrayDeque<Wrapper>(); int position = 0, // position in output line level = 1, // level being processed current; // value for node ABOUT to process // level-order traversal: initialize the work queue with the root queue.offer(new Wrapper(node, level));// node initially IS the root while ( ! queue.isEmpty() ) // Go there's nothing left to do! { Wrapper item = queue.remove(); node = item.node; current = item.level; if (node.left != null) // Enqueue child nodes queue.offer(new Wrapper(node.left, current+1)); if (node.right != null) queue.offer(new Wrapper(node.right, current+1)); // Check for line-break: change in tree level if ( current != level ) { System.out.println(); position = 0; level = current; } // skip over to proper position for ( ; position < node.util ; position++ ) System.out.print (" "); System.out.printf ("%2s", node.data);
position += 2; // Update position for the output just done } // end while System.out.println(); // Final line termination. } // end pretty(BSTnode) static intnewHt ( BSTnode node ) { BSTnodelt = node.left, rt = node.right; if ( lt == null && rt == null ) // Leaf node is height 1 return 1; else if ( lt == null ) // Half node cases return 1 + rt.height; else if (rt == null ) return 1 + lt.height; else // Full node --- need java.lang.Math.max return 1 + Math.max(lt.height, rt.height); } // end newHt() // Return the size based on the children; node must NOT be null. static intnewSize( BSTnode node ) { BSTnodelt = node.left, rt = node.right;
if ( lt == null && rt == null ) // Leaf node has size 1 return 1; else if ( lt == null ) // Half node cases return 1 + rt.size; else if (rt == null ) return 1 + lt.size; else // Full node --- do the sum return 1 + lt.size + rt.size; } // end newSize() BSTnode build( Comparable data ) { BSTnodertn; if (free == null) { rtn = new BSTnode (data); if ( rtn == null ) { System.err.println ("ALLOCATION ERROR. Abort execution."); System.exit(7); } } else { rtn = free; free = free.right; rtn.data = data; rtn.height = rtn.size = 1; // Leaf node rtn.left = null; rtn.right = null; } return rtn; } void recycle( BSTnode node ) { if ( DEBUG ) System.out.println ("Recycling node \"" + node.data + '"'); node.left = null; node.right = free; free = node; } // end recycle } // end class BST
AVLverbose.java public class AVLverbose extends AVL { static final boolean TRACE = true ; // Over-ride AVL value // If necessary, do rotations to enforce the AVL condition BSTnodeadjustAVL(BSTnode node) { intltHt = node.left == null ? 0 : node.left.height, rtHt = node.right == null ? 0 : node.right.height, diff = ltHt - rtHt; if ( Math.abs(diff) > 1 ) // AVL condition is violated { if (TRACE) System.out.print ("Adjusting AVL at node " + node.data); if ( ltHt > rtHt )// left side two longer than right { intltCk = node.left.left == null ? 0 : node.left.left.height, rtCk = node.left.right == null ? 0 : node.left.right.height; if (TRACE) { if ( ltCk < rtCk ) // Make left the longer { node.left = rotateLeft (node.left); System.out.println (". Weiss case 2, Sahni LR"); } else System.out.println (". Weiss case 1, Sahni LL"); } else {
if ( ltCk < rtCk ) // Make left the longer node.left = rotateLeft (node.left); } // end if (TRACE) / else node = rotateRight (node); // Adjust node itself } else // Mirror image logic to that above: right than left { intltCk = node.right.left == null ? -1 : node.right.left.height, rtCk = node.right.right == null ? -1 : node.right.right.height; if (TRACE) { if ( ltCk > rtCk ) { node.right = rotateRight (node.right); System.out.println (". Weiss case 3, Sahni RL"); } else System.out.println (". Weiss case 4, Sahni RR"); } // end if (TRACE) / else else { if ( ltCk > rtCk ) node.right = rotateRight (node.right); } node = rotateLeft (node); } } adjustNode(node); // Whatever has happend, adjust height and size. return node; } // end adjustAVL() } // end class AVLverbose