Subversion Repositories programming

Rev

Rev 100 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
28 irasnyd 1
// Written by Ira Snyder
2
// Due Date: 11-15-2004
3
// Project #3
38 irasnyd 4
// People Helped: Allen Oliver
108 ira 5
// License: Public Domain (added 07-11-2005)
28 irasnyd 6
 
7
import java.io.*;
8
import java.util.*;
9
class BinaryTree {
10
    private Object root;
11
    private BinaryTree left, right;
12
 
13
    //constructors ----------------------------------------------------------
29 irasnyd 14
 
15
    // constructor to create a singleton tree
16
    // Precondition:  root is a non-null Object
17
    // Postcondition: returns a BinaryTree with the Object given as the root
18
    //                data, and null left and right subtrees
19
    public BinaryTree( Object root ) { 
20
        this.root = root;
21
        this.left = null;
22
        this.right = null;
23
    }
24
 
25
    // constructor to create a BinaryTree with the given Object as the root
26
    // data, and the given BinaryTrees as the left and right subtrees
27
    // Precondition:  root is a non-null Object (right and left CAN be null
28
    // Postcondition: returns a BinaryTree with the given root data and
29
    //                the given left and right subtrees
30
    public BinaryTree( Object root, BinaryTree left, BinaryTree right ) {
31
        this.root = root;
32
        this.left = left;
33
        this.right = right;
34
    }
28 irasnyd 35
 
29 irasnyd 36
    // copy constructor, creates a tree which has the same structure and
37
    // whose nodes reference the same objects as the _that_ tree
36 irasnyd 38
    public BinaryTree( BinaryTree that ) {
39
        root = that.root;
40
        left = null; right = null;
41
 
42
        if( that.left != null ) { left = new BinaryTree(that.left); }
43
        if( that.right != null ) { right = new BinaryTree(that.right); }
29 irasnyd 44
    }
45
 
28 irasnyd 46
    //getter methods --------------------------------------------------------
47
 
29 irasnyd 48
    // method which returns the root data
49
    // Precondition:  none
50
    // Postcondition: return the root data
51
    public Object getRoot() { return root; }
52
 
53
    // method which will return a reference to the left subtree
54
    // Precondition:  none
55
    // Postcondition: returns a reference to the left subtree
56
    public BinaryTree getLeft() { return left; }
57
 
58
    // method which will return a reference to the right subtree
59
    // Precondition:  none
60
    // Postcondition: returns a reference to the right subtree
61
    public BinaryTree getRight() { return right; }
62
 
28 irasnyd 63
    //setter methods --------------------------------------------------------
64
 
29 irasnyd 65
    // method which updates the root data
66
    // Precondition:  root is non-null
67
    // Postcondition: sets this.root to the new data, returns the old data
68
    public Object setRoot( Object root ) { 
69
        Object temp = this.root;
70
        this.root = root;
71
        return temp;
72
    }
73
 
74
    // method which updates the left subtree
75
    // Precondition:  none ( left CAN be null )
76
    // Postcondition: sets this.left to the new subtree,
77
    //                returns a reference to the old left subtree
78
    public BinaryTree setLeft( BinaryTree left ) { 
79
        BinaryTree temp = this.left;
80
        this.left = left;
81
        return temp;
82
    }
83
 
84
    // method which update the right subtree
85
    // Precondition:  none ( right CAN be null )
86
    // Postcondition: sets this.right to the new subtree,
87
    //                returns a reference to the old right subtree
88
    public BinaryTree setRight( BinaryTree right ) {
89
        BinaryTree temp = this.right;
90
        this.right = right;
91
        return temp;
92
    }
93
 
28 irasnyd 94
    //toString method -------------------------------------------------------
95
 
29 irasnyd 96
    // returns a String representation of the BinaryTree
30 irasnyd 97
    // Precondition:  none
98
    // Postcondition: returns a string representation of the BinaryTree
29 irasnyd 99
    public String toString() { 
100
        String sLeft = "";
101
        String sRight = "";
102
        String answer = new String();
103
 
30 irasnyd 104
        //get the left tree's string representation (if it exists)
29 irasnyd 105
        if( !(left == null) ) { sLeft = left.toString(); }
106
 
30 irasnyd 107
        //get the right tree's string representation (if it exists)
29 irasnyd 108
        if( !(right == null) ) { sRight = right.toString(); }
109
 
30 irasnyd 110
        //assemble the string to return
29 irasnyd 111
        answer = "(";
112
        if( !sLeft.equals("") ) { answer += sLeft + ","; }
113
        answer += root.toString();
114
        if( !sRight.equals("") ) { answer += "," + sRight; }
115
        answer += ")";
116
 
30 irasnyd 117
        //return the assembled string
29 irasnyd 118
        return answer;
119
    }
30 irasnyd 120
 
28 irasnyd 121
    //misc methods ----------------------------------------------------------
33 irasnyd 122
 
123
    // method to check if the current node is a leaf
124
    // Precondition:  none
125
    // Postcondition: returns true if the current node is a leaf, and false
126
    //                in any other case
30 irasnyd 127
    public boolean isLeaf() { 
31 irasnyd 128
        if( (left == null) && (right == null) ) { return true; }
30 irasnyd 129
        return false;
130
    }
31 irasnyd 131
 
33 irasnyd 132
    // method to find the size of the tree
133
    // Precondition:  none
134
    // Postcondition: returns the size of the tree
31 irasnyd 135
    public int size() { 
136
        int answer=1; // 1 for the node we are at
137
        if( !(left == null) ) { answer += left.size(); }
138
        if( !(right == null) ) { answer += right.size(); }
139
 
140
        return answer;
141
    }
142
 
33 irasnyd 143
    // method to calculate the height of the tree
144
    // Precondition:  none
145
    // Postcondition: returns the height of the tree
31 irasnyd 146
    public int height() {
147
        if( this.isLeaf() ) { return 0; }
37 irasnyd 148
        int l=0,r=0; 
149
 
150
        if( left != null ) { l = 1 + left.height(); }
151
        if( right != null ) { r = 1 + right.height(); }
152
 
31 irasnyd 153
        return Math.max(l,r);
154
    }
32 irasnyd 155
 
33 irasnyd 156
    // method to search the tree for an object
157
    // Precondition:  object is non-null
158
    // Postcondition: returns true if the tree contains the object,
159
    //                and false if the tree doesn't contain the object
32 irasnyd 160
    public boolean contains( Object object ) { 
161
        if( root.equals(object) ) { return true; }
37 irasnyd 162
        //if( this.isLeaf() ) { return false; }
163
 
164
        boolean l=false, r=false;
165
        if( left != null ) { l=left.contains(object); }
166
        if( right != null ) { r=right.contains(object); }
167
 
168
        return l || r;
32 irasnyd 169
    }
170
 
33 irasnyd 171
    // method to find the number of leaves in the tree
172
    // Precondition:  none
173
    // Postcondition: returns the number of leaves in the tree
32 irasnyd 174
    public int numLeaves() { 
175
        if( this.isLeaf() ) { return 1; }
37 irasnyd 176
 
177
        int l=0, r=0;
178
 
179
        if( left != null ) { l = left.numLeaves(); }
180
        if( right != null ) { r = right.numLeaves(); }
181
 
182
        return l + r;
32 irasnyd 183
    }
184
 
33 irasnyd 185
    // method to find the number of a certain object in the tree
186
    // Precondition:  the object in non-null
187
    // Postcondition: returns the number of the object that
188
    //                are in the tree
32 irasnyd 189
    public int count( Object x ) { 
190
        int answer=0;
191
        if( root.equals(x) ) { answer=1; }
192
        if( !(left == null) ) { answer += left.count(x); }
193
        if( !(right == null) ) { answer += right.count(x); }
194
        return answer;
195
    }
33 irasnyd 196
 
197
    // method to check if the tree is full
198
    // Precondition:  none
199
    // Postcondition: returns true if the tree is a full tree, 
200
    //                and false if the tree is not a full tree
201
    public boolean isFull() { 
202
        if( this.isLeaf() ) { return true; }
203
        if( !(left.height() == right.height()) ) { return false; }
34 irasnyd 204
        if( left.isFull() && right.isFull() ) { return true; }
205
        return false;
33 irasnyd 206
    }
207
 
208
    // method to check if the tree is balanced
209
    // Precondition:  none
210
    // Postcondition: returns true if the tree is balanced, false otherwise
37 irasnyd 211
    public boolean isBalanced() {
34 irasnyd 212
        if( this.isLeaf() ) { return true; }
37 irasnyd 213
 
214
        //get left and right heights as applicable
215
        int l=0, r=0;
216
        if( left != null ) { l = left.height(); }
217
        if( right != null ) { r = right.height(); }
218
 
219
        //check for the criteria of balance. If we are balanced, then
220
        //check our subtrees for balance recursively
221
        if( Math.abs( l-r ) < 2 ) {
222
            if( left != null && right != null ) //check both
223
                return left.isBalanced() && right.isBalanced();
224
            if( left != null ) //right is null (check left)
225
                return left.isBalanced();
226
            //left is null, right is not null
227
            return right.isBalanced(); //check right
228
        }
229
        return false; //the criteria of balance was not met
34 irasnyd 230
    }
35 irasnyd 231
 
36 irasnyd 232
    // method to get the total path length of the current tree
233
    // Precondition:  none
234
    // Postcondition: returns the sum of all the root to node paths in
235
    //                the tree
35 irasnyd 236
    public int pathLength() {
237
        int answer=0;
238
        Queue queue = new Queue();
239
        queue.enqueue(this);
240
 
241
        while( !queue.isEmpty() ) {
242
            BinaryTree temp = (BinaryTree)queue.dequeue();
243
            answer += level(temp.root);
244
            if( temp.left != null ) { queue.enqueue(temp.left); }
245
            if( temp.right != null ) { queue.enqueue(temp.right); }
246
        }
247
 
248
        return answer;
34 irasnyd 249
    }
36 irasnyd 250
 
251
    // method to create a reverse of the tree
252
    // Precondition:  none
253
    // Postcondition: returns a new BinaryTree with the structure
254
    //                reversed as if it were seen in a mirror
35 irasnyd 255
    public BinaryTree reverse() { 
256
        //both left and right are null
257
        if( this.isLeaf() ) { return new BinaryTree(root); }
258
 
259
        //left must be null, right must not be null
260
        if( this.left == null ) 
261
            return new BinaryTree(root,right.reverse(),null);
262
 
263
        //right must be null, left must not be null
264
        if( this.right == null )
265
            return new BinaryTree(root,null,left.reverse());
266
 
267
        //both sides are not null
268
        return new BinaryTree(root,right.reverse(),left.reverse());
269
    }
270
 
36 irasnyd 271
    // a method to find the level of an object in the tree
272
    // Precondition:  x is not null
273
    // Postcondition: returns the level of the deepest object x in the tree
34 irasnyd 274
    public int level( Object x ) { 
275
        if( !this.contains(x) ) { return -1; }  //not found
276
        if( this.root.equals(x) ) { return 0; } //found here
37 irasnyd 277
        int ansLeft=0, ansRight=0;
278
        if( left != null ) { ansLeft = left.level(x); }
279
        if( right != null ) { ansRight = right.level(x); }
34 irasnyd 280
 
281
        int answer = Math.max(ansLeft,ansRight);
282
        if( answer >= 0 ) { return answer + 1; }
283
        return answer;
33 irasnyd 284
    }
35 irasnyd 285
 
36 irasnyd 286
    // method to check if the current tree is disjoint from "that" tree
287
    // disjoint: no element in both this tree and that tree
288
    // Precondition:  none
289
    // Postcondition: returns true if and only if no element from "that"
290
    //                tree is in "this" tree
35 irasnyd 291
    public boolean isDisjointFrom( BinaryTree that ) { 
292
        if( that == null ) { return true; }
293
        if( this.contains(that.root) ) { return false; }
294
 
295
        return isDisjointFrom(that.left) && isDisjointFrom(that.right);
296
    }
297
 
36 irasnyd 298
    // method to check if a tree is valid
299
    // valid: all of it's subtrees are disjoint
300
    // Precondition:  none
301
    // Postcondition: returns true if the tree is valid, false otherwise
35 irasnyd 302
    public boolean isValid() { 
303
        if( this.isLeaf() ) { return true; }
304
        boolean answer;
305
 
306
        if( left != null ) { answer = left.isDisjointFrom(right); }
307
        else { answer = right.isDisjointFrom(left); }
308
 
309
        return answer;
310
    }
311
 
36 irasnyd 312
    // method to check if one tree is equal to another
313
    // Precondition:  object should be a BinaryTree (this is checked anyway)
314
    // Postcondition: return true only if both trees are equal
34 irasnyd 315
    public boolean equals( Object object ) {
316
        //if we are not a BinaryTree, return false
317
        if( !(object instanceof BinaryTree) ) { return false; } 
318
        BinaryTree x = (BinaryTree)object; //typed instance of Object
319
 
320
        //temporary answer holding variables
321
        boolean ansLeft=false, ansRight=false;
322
 
323
        //check for the root data equality
324
        if( !this.root.equals(x.root) ) { return false; }
325
 
36 irasnyd 326
        if( left != null ) { //check left
34 irasnyd 327
            if( left.equals(x.left) ) { ansLeft = true; }
36 irasnyd 328
        }
329
 
330
        if( right != null ) { //check right
34 irasnyd 331
            if( right.equals(x.right) ) { ansRight = true; }
332
        }
333
 
334
        //if both are null, we are still okay
335
        if( left == null && x.left == null ) { ansLeft = true; }
336
        if( right == null && x.right == null ) { ansRight = true; }
337
 
338
        //check that both left and right are okay
339
        if( ansLeft == true && ansRight == true ) { return true; }
340
        return false; //return false if any condition was not met
341
    }
342
 
343
 
344
    //printing methods ------------------------------------------------------
38 irasnyd 345
 
346
    // method to print the tree in the following order: root,left,right
347
    // Precondition:  none
348
    // Postcondition: the tree will be printed to System.out in preOrder
34 irasnyd 349
    public static void preOrderPrint( BinaryTree tree ) { 
350
        System.out.print( tree.root + " " );
351
        if( tree.left != null ) { preOrderPrint( tree.left ); }
352
        if( tree.right != null ) { preOrderPrint( tree.right ); }
353
    }
354
 
38 irasnyd 355
    // method to print the tree in the following order: left,right,root
356
    // Precondition:  none
357
    // Postcondition: the tree will be printed to System.out in postOrder
34 irasnyd 358
    public static void postOrderPrint( BinaryTree tree ) { 
359
        if( tree.left != null ) { postOrderPrint( tree.left ); }
360
        if( tree.right != null ) { postOrderPrint( tree.right ); }
361
        System.out.print( tree.root + " " );
362
    }
363
 
38 irasnyd 364
    // method to print the tree by level
365
    // Precondition:  none
366
    // Postcondition: the tree will be printed to System.out by level
34 irasnyd 367
    public static void levelOrderPrint( BinaryTree tree ) { 
368
        Queue queue = new Queue();
369
        queue.enqueue(tree);
28 irasnyd 370
 
34 irasnyd 371
        while( !queue.isEmpty() ) {
372
            BinaryTree temp = (BinaryTree)queue.dequeue();
373
            System.out.print( temp.root + " " );
374
            if( temp.left != null ) { queue.enqueue(temp.left); }
375
            if( temp.right != null ) { queue.enqueue(temp.right); }
376
        }   
377
    }
378
 
38 irasnyd 379
    // method to print the tree in the following order: left,root,right
380
    // Precondition:  none
381
    // Postcondition: the tree will be printed to System.out in inOrder
34 irasnyd 382
    public static void inOrderPrint( BinaryTree tree ) { 
383
        if( tree.left != null ) { inOrderPrint(tree.left); }
384
        System.out.print( tree.root + " " );
385
        if( tree.right != null ) { inOrderPrint(tree.right); }
386
    }
28 irasnyd 387
}
388