Subversion Repositories programming

Rev

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