Subversion Repositories programming

Rev

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