Subversion Repositories programming

Rev

Rev 50 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
41 irasnyd 1
// Written by Ira Snyder
2
// Due Date: 11-24-2004
3
// Project #4
46 irasnyd 4
// Helped and was Helped By: Allen Oliver
5
// Got information from: 
6
//     http://www.cs.dartmouth.edu/~chepner/cs15/notes/08_bst.html
41 irasnyd 7
 
8
import java.io.*;
9
import java.util.*;
10
 
11
class AVLTree {
12
    private int key, height;
43 irasnyd 13
    private Object data;
41 irasnyd 14
    private AVLTree left, right;
15
 
46 irasnyd 16
    //create an empty tree to be used instead of checking
17
    //for nulls all over the place
41 irasnyd 18
    public static final AVLTree NIL = new AVLTree();
19
 
46 irasnyd 20
    //constructor for the basic AVLTree
43 irasnyd 21
    public AVLTree( int key, Object data ) {
41 irasnyd 22
        this.key = key;
43 irasnyd 23
        this.data = data;
41 irasnyd 24
        left = right = NIL;
25
    }
46 irasnyd 26
 
27
    //method to insert a new key-data pair into the tree
43 irasnyd 28
    public boolean add( int key, Object data ) {
41 irasnyd 29
        int oldSize = size();
43 irasnyd 30
        grow(key,data);
41 irasnyd 31
        return size() > oldSize;
32
    }
33
 
46 irasnyd 34
    //provide name mapping for add
43 irasnyd 35
    public boolean insert( int key, Object data ) {
36
        return add(key,data);
37
    }
41 irasnyd 38
 
46 irasnyd 39
    //method to add an element to a tree
40
    private AVLTree grow( int key, Object data ) {
43 irasnyd 41
        if( this == NIL ) return new AVLTree(key,data);
46 irasnyd 42
 
43
        //prevent key dupes, update data
44
        if( key == this.key ) { this.data = data; return this; } 
43 irasnyd 45
        if( key < this.key ) left = left.grow(key,data);
46
        else right = right.grow(key,data);
47
 
46 irasnyd 48
        rebalance(); //fix the balance as we recurse back up
41 irasnyd 49
 
50
        height = 1 + Math.max(left.height,right.height);
51
        return this;
52
    }
53
 
46 irasnyd 54
    //method to return the size of the tree
41 irasnyd 55
    public int size() {
56
        if( this == NIL ) return 0;
57
        return 1 + left.size() + right.size();
58
    }
59
 
42 irasnyd 60
    //I like the BinaryTree toString better than the author's toString()
61
    //so I used it here instead. I left the author's code for completeness.
62
    /*
41 irasnyd 63
    public String toString() {
64
        if( this == NIL ) return "";
65
        return left + " " + key + " " + right;
66
    }
42 irasnyd 67
    */
68
 
46 irasnyd 69
    //method to print the tree as a String
42 irasnyd 70
    public String toString() {
71
 
72
        if( this == NIL ) return "()";
73
 
74
        String sLeft = sLeft = left.toString();
75
        String sRight = sRight = right.toString();
76
        String answer = new String();
77
 
78
        //assemble the string to return
79
        answer = "(";
80
        if( !sLeft.equals("()") ) { answer += sLeft + ","; }
81
        answer += key;
82
        if( !sRight.equals("()") ) { answer += "," + sRight; }
83
        answer += ")";
84
 
85
        //return the assembled string
86
        return answer;
87
    }
88
 
46 irasnyd 89
    //constructor to make the empty tree
90
    private AVLTree() {
41 irasnyd 91
        left = right = this;
92
        height = -1;
93
    }
46 irasnyd 94
 
95
    //constructor to make a new AVLTree given a key-data pair, and left
96
    //and right subtrees
43 irasnyd 97
    private AVLTree( int key, Object data, AVLTree left, AVLTree right ) {
41 irasnyd 98
        this.key = key;
43 irasnyd 99
        this.data = data;
41 irasnyd 100
        this.left = left;
101
        this.right = right;
102
        height = 1 + Math.max(left.height,right.height);
103
    }
46 irasnyd 104
 
105
    //method to rebalance the tree if it is out of balance, using rotations
41 irasnyd 106
    private void rebalance() {
107
        if( right.height > (left.height + 1) ) {
108
            if( right.left.height > right.right.height ) right.rotateRight();
109
            rotateLeft();
110
        }
111
        else if( left.height > (right.height + 1) ) {
112
            if( left.right.height > left.left.height ) left.rotateLeft();
113
            rotateRight();
114
        }
115
    }
46 irasnyd 116
 
117
    //method to rotate the tree to the left
41 irasnyd 118
    private void rotateLeft() {
43 irasnyd 119
        left = new AVLTree(key,data,left,right.left);
41 irasnyd 120
        key = right.key;
43 irasnyd 121
        data = right.data;
41 irasnyd 122
        right = right.right;
123
    }
124
 
46 irasnyd 125
    //method to rotate the tree to the right
41 irasnyd 126
    private void rotateRight() {
43 irasnyd 127
        right = new AVLTree(key,data,left.right,right);
41 irasnyd 128
        key = left.key;
43 irasnyd 129
        data = left.data;
41 irasnyd 130
        left = left.left;
131
    }
132
 
46 irasnyd 133
    //method to return the height of the tree
42 irasnyd 134
    public int getHeight() { return height; }
43 irasnyd 135
 
46 irasnyd 136
    //method to return the height of the subtree with the
137
    //given key
43 irasnyd 138
    public int getHeight( int key ) {
139
        if( this == NIL ) { return -1; }
140
        if( key == this.key ) { return getHeight(); }
141
        if( key < this.key ) { return left.getHeight(key); }
142
        return right.getHeight(key);
143
    }
42 irasnyd 144
 
46 irasnyd 145
    //method to return the left subtree
42 irasnyd 146
    public AVLTree getLeft() { 
147
        if( this == NIL ) { return NIL; }
148
        return left;
149
    }
46 irasnyd 150
 
151
    //method to return the left subtree of the subtree with the
152
    //given key
43 irasnyd 153
    public AVLTree getLeft( int key ) {
154
        if( this == NIL ) { return null; } //key not in tree
155
        if( key == this.key ) { return getLeft(); }
156
        if( key < this.key ) { return left.getLeft(key); }
157
        return right.getLeft(key);
158
    }
42 irasnyd 159
 
46 irasnyd 160
    //method to return the right subtree
43 irasnyd 161
    public AVLTree getRight() {
42 irasnyd 162
        if( this == NIL ) { return NIL; }
163
        return right;
164
    }
46 irasnyd 165
 
166
    //method to return the right subtree of the subtree with the
167
    //given key
43 irasnyd 168
    public AVLTree getRight( int key ) {
169
        if( this == NIL ) { return null; } //key not in tree
170
        if( key == this.key ) { return getRight(); }
171
        if( key < this.key ) { return left.getRight(key); }
172
        return right.getRight(key);
173
    }
42 irasnyd 174
 
46 irasnyd 175
    //method to return the key of the root
43 irasnyd 176
    public int getRoot() { return key; }
46 irasnyd 177
 
178
    //method to return the key of the root
43 irasnyd 179
    public int getKey() { return key; }
46 irasnyd 180
 
181
    //method to return the data of the root
43 irasnyd 182
    public Object getData() { return data; }
42 irasnyd 183
 
46 irasnyd 184
    //method to see if the tree contains a key
42 irasnyd 185
    public boolean contains( int x ) { 
186
        if( this == NIL ) { return false; }
187
        if( key == x ) { return true; }
188
 
189
        return left.contains(x) || right.contains(x);
190
    }
191
 
46 irasnyd 192
    //return the data associated with a given key
43 irasnyd 193
    public Object get( int key ) {
42 irasnyd 194
        if( this == NIL ) { return NIL; }
43 irasnyd 195
        if( key == this.key ) { return data; }
42 irasnyd 196
 
43 irasnyd 197
        if( key < this.key ) { return left.get(key); }
198
        return right.get(key);
42 irasnyd 199
    }
200
 
46 irasnyd 201
    //check if two trees are equals
42 irasnyd 202
    public boolean equals( Object object ) { 
203
        if( !(object instanceof AVLTree) ) { return false; }
204
 
205
        AVLTree temp = (AVLTree)object; //make it typed
206
 
207
        boolean l=false, r=false;
208
 
209
        //check the left
210
        if( left == NIL && temp.left == NIL ) l = true;
211
        else l = left.equals(temp.left);
212
 
213
        //check the right
214
        if( right == NIL && temp.right == NIL ) r = true;
215
        else r = right.equals(temp.right);
216
 
217
        return (temp.key == key) && l && r;
218
    }
219
 
46 irasnyd 220
    //method to create a new tree from an array of keys,
221
    //and an array of data
43 irasnyd 222
    public AVLTree( int[] keys, Object[] data ) { 
46 irasnyd 223
        //this(keys[0],data[0]); //create a new tree
42 irasnyd 224
 
46 irasnyd 225
        if( keys.length != data.length ) { throw new IllegalArgumentException(); }
226
 
227
        this.key = keys[0];
228
        this.data = data[0];
229
        left = right = NIL;
230
 
42 irasnyd 231
        //call add() for every element in the array
43 irasnyd 232
        for( int i=1; i < keys.length; i++ ) add(keys[i],data[i]);
42 irasnyd 233
    }
45 irasnyd 234
 
46 irasnyd 235
    //method to remove a key-data pair from the tree
45 irasnyd 236
    public boolean remove( int key ) {
237
        if( !contains(key) ) { return false; }
238
        removeHelper(this,key);
239
        if( contains(key) ) { return false; }
240
        return true;
241
    }
46 irasnyd 242
 
243
    //a helper method for remove, which performs the actual recursion
45 irasnyd 244
    private AVLTree removeHelper( AVLTree tree, int key ) {
245
        if( tree == NIL ) { return NIL; }
246
        else if( key < tree.key ) { tree.left = removeHelper(tree.left,key); }
247
        else if( key > tree.key ) { tree.right = removeHelper(tree.right,key); }
46 irasnyd 248
        else if( tree.left != NIL && tree.right != NIL ) { 
249
            tree = deleteMinimum(tree.right); 
250
        }
45 irasnyd 251
        else if( tree.left != NIL ) { tree = tree.left; }
252
        else { tree = tree.right; }
46 irasnyd 253
 
254
        tree.rebalance(); //rebalance as we recurse back up
45 irasnyd 255
        return tree;
256
    }
42 irasnyd 257
 
46 irasnyd 258
    //method to remove the minimum element in a tree
45 irasnyd 259
    private AVLTree deleteMinimum( AVLTree tree ) {
44 irasnyd 260
        if( tree == NIL ) { return NIL; }
261
        if( tree.left == NIL && tree.right == NIL ) { return NIL; }
262
        if( tree.left == NIL ) { 
263
            return new AVLTree(tree.right.key,tree.right.data,
264
                               tree.right.left,tree.right.right); 
42 irasnyd 265
        }
44 irasnyd 266
        return new AVLTree(tree.key,tree.data,deleteMinimum(tree.left),tree.right);
42 irasnyd 267
    }
43 irasnyd 268
 
46 irasnyd 269
    //method to print a tree InOrder
43 irasnyd 270
    public static void printInOrder( AVLTree tree ) {
271
        Queue queue = new Queue();
272
        queue.enqueue(tree);
273
 
274
        while( !queue.isEmpty() ) {
275
            AVLTree temp = (AVLTree)queue.dequeue();
50 irasnyd 276
            System.out.print(temp.getKey()+" ");
43 irasnyd 277
            if( temp.getLeft() != NIL ) { queue.enqueue(temp.getLeft()); }
278
            if( temp.getRight() != NIL ) { queue.enqueue(temp.getRight()); }
279
        }
280
    }
281
 
46 irasnyd 282
    //method to print a tree in PreOrder
43 irasnyd 283
    public static void printPreOrder( AVLTree tree ) {
284
        if( tree == NIL ) return;
285
 
50 irasnyd 286
        System.out.print(tree.getKey()+" ");
43 irasnyd 287
        AVLTree.printPreOrder( tree.getLeft() );
288
        AVLTree.printPreOrder( tree.getRight() );
289
    }
290
 
41 irasnyd 291
} //end AVLTree class
292