Subversion Repositories programming

Rev

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