Class Name: 
kiasan.examples.avltree.AvlTree

Report Rendered: Mon May 04 11:28:33 CDT 2009, by Sireum/Kiasan for Java v0.1.20090504

Methods Covered:
PercentRatio
Class / Method T E Instruction Coverage Branch Coverage Time
190 0
  45/45
  100%
  10/10
  100%
0.196s
20 0
  33/33
  100%
  8/8
  100%
0.058s
20 0
  33/33
  100%
  8/8
  100%
0.058s
190 0
  207/207
  100%
  18/18
  100%
0.689s
Total
420 0
  318/318
  100%
  44/44
  100%
1.001s
Source Code:
1   package kiasan.examples.avltree;
2   
3   import kiasan.examples.common.Range;
4   
5   /**
6    * Implements an AVL tree. Note that all "matching" is based on the compareTo
7    * method.
8    * 
9    * @author Mark Allen Weiss
10   */
11  public class AvlTree {
12    /**
13     * Double rotate binary tree node: first left child with its right child; then
14     * node k3 with new left child. For AVL trees, this is a double rotation for
15     * case 2. Update heights, then return new root.
16     */
17    private static AvlNode doubleWithLeftChild(final AvlNode k3) {
18      k3.left = AvlTree.rotateWithRightChild(k3.left);
19      return AvlTree.rotateWithLeftChild(k3);
20    }
21  
22    /**
23     * Double rotate binary tree node: first right child with its left child; then
24     * node k1 with new right child. For AVL trees, this is a double rotation for
25     * case 3. Update heights, then return new root.
26     */
27    private static AvlNode doubleWithRightChild(final AvlNode k1) {
28      k1.right = AvlTree.rotateWithLeftChild(k1.right);
29      return AvlTree.rotateWithRightChild(k1);
30    }
31  
32    /**
33     * Return the height of node t, or -1, if null.
34     */
35    private static int height(final AvlNode t) {
36      return t == null ? -1 : t.height;
37    }
38  
39    /**
40     * Return maximum of lhs and rhs.
41     */
42    private static int max(final int lhs, final int rhs) {
43      return lhs > rhs ? lhs : rhs;
44    }
45  
46    /**
47     * Rotate binary tree node with left child. For AVL trees, this is a single
48     * rotation for case 1. Update heights, then return new root.
49     */
50    private static AvlNode rotateWithLeftChild(final AvlNode k2) {
51      final AvlNode k1 = k2.left;
52      k2.left = k1.right;
53      k1.right = k2;
54      k2.height = AvlTree.max(AvlTree.height(k2.left), AvlTree.height(k2.right)) + 1;
55      k1.height = AvlTree.max(AvlTree.height(k1.left), k2.height) + 1;
56      return k1;
57    }
58  
59    /**
60     * Rotate binary tree node with right child. For AVL trees, this is a single
61     * rotation for case 4. Update heights, then return new root.
62     */
63    private static AvlNode rotateWithRightChild(final AvlNode k1) {
64      final AvlNode k2 = k1.right;
65      k1.right = k2.left;
66      k2.left = k1;
67      k1.height = AvlTree.max(AvlTree.height(k1.left), AvlTree.height(k1.right)) + 1;
68      k2.height = AvlTree.max(AvlTree.height(k2.right), k1.height) + 1;
69      return k2;
70    }
71  
72    /** The tree root. */
73    private AvlNode root;
74  
75    /**
76     * Construct the tree.
77     */
78    public AvlTree() {
79      this.root = null;
80    }
81  
82    boolean balanced() {
83      return balanced(this.root);
84    }
85  
86    private boolean balanced(final AvlNode an) {
87      if (an == null) {
88        return true;
89      }
90      final int lh = AvlTree.height(an.left);
91      final int rh = AvlTree.height(an.right);
92      return ((lh == rh) || (lh == rh + 1) || (lh + 1 == rh))
93          && balanced(an.left) && balanced(an.right);
94    }
95  
96    /**
97     * Internal method to get element field.
98     * 
99     * @param t
100    *          the node.
101    * @return the element field or null if t is null.
102    */
103   private int elementAt(final AvlNode t) {
104     return t == null ? -1 : t.element;
105   }
106 
107   /**
108    * Find an item in the tree.
109    * 
110    * @param x
111    *          the item to search for.
112    * @return the matching item or null if not found.
113    */
114   //@ requires this.ordered() && this.wellFormed() && this.balanced();
115   //@ ensures this.ordered() && this.wellFormed() && this.balanced();
116   public int find(final int x) {
117     return elementAt(find(x, this.root));
118   }
119 
120   /**
121    * Internal method to find an item in a subtree.
122    * 
123    * @param x
124    *          is item to search for.
125    * @param t
126    *          the node that roots the tree.
127    * @return node containing the matched item.
128    */
129   private AvlNode find(final int x, AvlNode t) {
130     while (!= null) {
131       if (< t.element) {
132         t = t.left;
133       } else if (> t.element) {
134         t = t.right;
135       } else {
136         return t; // Match
137       }
138     }
139 
140     return null; // No match
141   }
142 
143   /**
144    * Find the largest item in the tree.
145    * 
146    * @return the largest item of null if empty.
147    */
148   //@requires this.ordered() && this.wellFormed() && this.balanced();
149   //@ensures this.ordered() && this.wellFormed() && this.balanced() && this.maxElement(\result);
150   public int findMax() {
151     return elementAt(findMax(this.root));
152   }
153 
154   /**
155    * Internal method to find the largest item in a subtree.
156    * 
157    * @param t
158    *          the node that roots the tree.
159    * @return node containing the largest item.
160    */
161   private AvlNode findMax(AvlNode t) {
162     if (== null) {
163       return t;
164     }
165 
166     while (t.right != null) {
167       t = t.right;
168     }
169     return t;
170   }
171 
172   /**
173    * Find the smallest item in the tree.
174    * 
175    * @return smallest item or null if empty.
176    */
177   //@requires this.ordered() && this.wellFormed() && this.balanced();
178   //@ensures this.ordered() && this.wellFormed() && this.balanced() && this.minElement(\result);
179   public int findMin() {
180     return elementAt(findMin(this.root));
181   }
182 
183   /**
184    * Internal method to find the smallest item in a subtree.
185    * 
186    * @param t
187    *          the node that roots the tree.
188    * @return node containing the smallest item.
189    */
190   private AvlNode findMin(AvlNode t) {
191     if (== null) {
192       return t;
193     }
194 
195     while (t.left != null) {
196       t = t.left;
197     }
198     return t;
199   }
200 
201   /**
202    * Insert into the tree; duplicates are ignored.
203    * 
204    * @param x
205    *          the item to insert.
206    */
207   //@ requires ordered() && wellFormed() && balanced();
208   //@ ensures balanced() && ordered();
209   public void insert(final int x) {
210     this.root = insert(x, this.root);
211   }
212 
213   /**
214    * Internal method to insert into a subtree.
215    * 
216    * @param x
217    *          the item to insert.
218    * @param t
219    *          the node that roots the tree.
220    * @return the new root.
221    */
222   private AvlNode insert(final int x, AvlNode t) {
223     if (== null) {
224       t = new AvlNode(x, null, null);
225     } else if (< t.element) {
226       t.left = insert(x, t.left);
227       if (AvlTree.height(t.left) - AvlTree.height(t.right) == 2) {
228         if (< t.left.element) {
229           t = AvlTree.rotateWithLeftChild(t);
230         } else {
231           t = AvlTree.doubleWithLeftChild(t);
232         }
233       }
234     } else if (> t.element) {
235       t.right = insert(x, t.right);
236       if (AvlTree.height(t.right) - AvlTree.height(t.left) == 2) {
237         if (> t.right.element) {
238           t = AvlTree.rotateWithRightChild(t);
239         } else {
240           t = AvlTree.doubleWithRightChild(t);
241         }
242       }
243     } else {
244       ; // Duplicate; do nothing
245     }
246     t.height = AvlTree.max(AvlTree.height(t.left), AvlTree.height(t.right)) + 1;
247     return t;
248   }
249 
250   /**
251    * Test if the tree is logically empty.
252    * 
253    * @return true if empty, false otherwise.
254    */
255   public boolean isEmpty() {
256     return this.root == null;
257   }
258 
259   /**
260    * Make the tree logically empty.
261    */
262   public void makeEmpty() {
263     this.root = null;
264   }
265 
266   boolean maxElement(final int max) {
267     return maxElement(max, this.root);
268   }
269 
270   private boolean maxElement(final int max, final AvlNode t) {
271     if (== null) {
272       return true;
273     }
274     if (max < t.element) {
275       return false;
276     }
277     return maxElement(max, t.left) && maxElement(max, t.right);
278   }
279 
280   boolean minElement(final int min) {
281     return minElement(min, this.root);
282   }
283 
284   private boolean minElement(final int min, final AvlNode t) {
285     if (== null) {
286       return true;
287     }
288     if (min > t.element) {
289       return false;
290     }
291     return minElement(min, t.left) && minElement(min, t.right);
292   }
293 
294   boolean ordered() {
295     return ordered(this.root, new Range());
296   }
297 
298   private boolean ordered(final AvlNode t, final Range range) {
299     if (== null) {
300       return true;
301     }
302     if (!range.inRange(t.element)) {
303       return false;
304     }
305     boolean ret = true;
306     ret = ordered(t.left, range.setUpper(t.element));
307     ret = ret && ordered(t.right, range.setLower(t.element));
308     return ret;
309   }
310 
311   /**
312    * Print the tree contents in sorted order.
313    */
314   public void printTree() {
315     if (isEmpty()) {
316       System.out.println("Empty tree");
317     } else {
318       printTree(this.root);
319     }
320   }
321 
322   /**
323    * Internal method to print a subtree in sorted order.
324    * 
325    * @param t
326    *          the node that roots the tree.
327    */
328   private void printTree(final AvlNode t) {
329     if (!= null) {
330       printTree(t.left);
331       System.out.println(t.element);
332       printTree(t.right);
333     }
334   }
335 
336   /**
337    * Remove from the tree. Nothing is done if x is not found.
338    * 
339    * @param x
340    *          the item to remove.
341    */
342   public void remove(final int x) {
343     // System.out.println( "Sorry, remove unimplemented" );
344   }
345 
346   boolean wellFormed() {
347     return wellFormed(this.root);
348   }
349 
350   private boolean wellFormed(final AvlNode an) {
351     if (an == null) {
352       return true;
353     }
354     if (AvlTree.height(an) != Math.max(AvlTree.height(an.left), AvlTree
355         .height(an.right)) + 1) {
356       return false;
357     }
358     return wellFormed(an.left) && wellFormed(an.right);
359   }
360 }