Subversion Repositories programming

Rev

Rev 45 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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