5
5
6
6
/**
7
7
* This class will check if a BinaryTree is balanced. A balanced binary tree is
8
- * defined as a binary tree where the differenced in height between the left and
8
+ * defined as a binary tree where the difference in height between the left and
9
9
* right subtree of each node differs by at most one.
10
- *
10
+ * <p>
11
11
* This can be done in both an iterative and recursive fashion. Below,
12
12
* `isBalancedRecursive()` is implemented in a recursive fashion, and
13
13
* `isBalancedIterative()` is implemented in an iterative fashion.
14
14
*
15
15
* @author [Ian Cowan](https://github.com/iccowan)
16
16
*/
17
17
public class CheckIfBinaryTreeBalanced {
18
-
19
- /**
20
- * This class implements the BinaryTree for these algorithms
21
- */
22
- class BinaryTree {
23
-
24
- /**
25
- * The root node of the binary tree
26
- */
27
- BTNode root = null ;
28
- }
29
-
30
- /**
31
- * This class implements the nodes for the binary tree
32
- */
33
- class BTNode {
34
-
35
- /**
36
- * The value of the node
37
- */
38
- int value ;
39
-
40
- /**
41
- * The left child of the node
42
- */
43
- BTNode left = null ;
44
-
45
- /**
46
- * The right child of the node
47
- */
48
- BTNode right = null ;
49
-
50
- /**
51
- * Constructor
52
- */
53
- BTNode (int value ) {
54
- this .value = value ;
55
- }
56
- }
57
-
58
18
/**
59
19
* Recursive is BT balanced implementation
60
20
*
61
- * @param binaryTree The binary tree to check if balanced
21
+ * @param root The binary tree to check if balanced
62
22
*/
63
- public boolean isBalancedRecursive (BinaryTree binaryTree ) {
23
+ public static boolean isBalancedRecursive (BinaryTree .Node root ) {
24
+ if (root == null ) {
25
+ return true ;
26
+ }
64
27
// Create an array of length 1 to keep track of our balance
65
- // Default to true. We use an array so we have an efficient mutable object
28
+ // Default to true. We use an array, so we have an efficient mutable object
66
29
boolean [] isBalanced = new boolean [1 ];
67
30
isBalanced [0 ] = true ;
68
31
69
- // Check for balance and return whether or not we are balanced
70
- isBalancedRecursive (binaryTree . root , 0 , isBalanced );
32
+ // Check for balance and return whether we are balanced
33
+ isBalancedRecursive (root , 0 , isBalanced );
71
34
return isBalanced [0 ];
72
35
}
73
36
@@ -76,11 +39,11 @@ public boolean isBalancedRecursive(BinaryTree binaryTree) {
76
39
* recursion. We effectively perform a modified post-order traversal where
77
40
* we are looking at the heights of both children of each node in the tree
78
41
*
79
- * @param node The current node to explore
80
- * @param depth The current depth of the node
42
+ * @param node The current node to explore
43
+ * @param depth The current depth of the node
81
44
* @param isBalanced The array of length 1 keeping track of our balance
82
45
*/
83
- private int isBalancedRecursive (BTNode node , int depth , boolean [] isBalanced ) {
46
+ private static int isBalancedRecursive (BinaryTree . Node node , int depth , boolean [] isBalanced ) {
84
47
// If the node is null, we should not explore it and the height is 0
85
48
// If the tree is already not balanced, might as well stop because we
86
49
// can't make it balanced now!
@@ -106,22 +69,26 @@ private int isBalancedRecursive(BTNode node, int depth, boolean[] isBalanced) {
106
69
/**
107
70
* Iterative is BT balanced implementation
108
71
*/
109
- public boolean isBalancedIterative (BinaryTree binaryTree ) {
72
+ public static boolean isBalancedIterative (BinaryTree .Node root ) {
73
+ if (root == null ) {
74
+ return true ;
75
+ }
76
+
110
77
// Default that we are balanced and our algo will prove it wrong
111
78
boolean isBalanced = true ;
112
79
113
80
// Create a stack for our post order traversal
114
- Stack <BTNode > nodeStack = new Stack <BTNode >();
81
+ Stack <BinaryTree . Node > nodeStack = new Stack <>();
115
82
116
83
// For post order traversal, we'll have to keep track of where we
117
84
// visited last
118
- BTNode lastVisited = null ;
85
+ BinaryTree . Node lastVisited = null ;
119
86
120
87
// Create a HashMap to keep track of the subtree heights for each node
121
- HashMap <BTNode , Integer > subtreeHeights = new HashMap <BTNode , Integer >();
88
+ HashMap <BinaryTree . Node , Integer > subtreeHeights = new HashMap <>();
122
89
123
90
// We begin at the root of the tree
124
- BTNode node = binaryTree . root ;
91
+ BinaryTree . Node node = root ;
125
92
126
93
// We loop while:
127
94
// - the node stack is empty and the node we explore is null
@@ -165,7 +132,7 @@ public boolean isBalancedIterative(BinaryTree binaryTree) {
165
132
}
166
133
167
134
// The height of the subtree containing this node is the
168
- // max of the left and right subtree heighs plus 1
135
+ // max of the left and right subtree heights plus 1
169
136
subtreeHeights .put (node , Math .max (rightHeight , leftHeight ) + 1 );
170
137
171
138
// We've now visited this node, so we pop it from the stack
@@ -182,86 +149,7 @@ public boolean isBalancedIterative(BinaryTree binaryTree) {
182
149
}
183
150
}
184
151
185
- // Return whether or not the tree is balanced
152
+ // Return whether the tree is balanced
186
153
return isBalanced ;
187
154
}
188
-
189
- /**
190
- * Generates the following unbalanced binary tree for testing 0 / \ / \ 0 0
191
- * / / \ / / \ 0 0 0 / \ / \ 0 0 / / 0
192
- */
193
- private BinaryTree buildUnbalancedTree () {
194
- BinaryTree tree = new BinaryTree ();
195
- tree .root = new BTNode (0 );
196
-
197
- BTNode root = tree .root ;
198
- root .left = new BTNode (0 );
199
- root .right = new BTNode (0 );
200
-
201
- BTNode left = root .left ;
202
- BTNode right = root .right ;
203
-
204
- left .left = new BTNode (0 );
205
- right .left = new BTNode (0 );
206
- right .right = new BTNode (0 );
207
- right .left .right = new BTNode (0 );
208
-
209
- left = left .left ;
210
- left .left = new BTNode (0 );
211
- left .left .left = new BTNode (0 );
212
- left .left .left .left = new BTNode (0 );
213
-
214
- return tree ;
215
- }
216
-
217
- /**
218
- * Generates the following balanced binary tree for testing 0 / \ / \ 0 0 /
219
- * \ / \ / 0 / \ 0 0 0 / / / / 0 0
220
- */
221
- private BinaryTree buildBalancedTree () {
222
- BinaryTree tree = new BinaryTree ();
223
- tree .root = new BTNode (0 );
224
-
225
- BTNode root = tree .root ;
226
- root .left = new BTNode (0 );
227
- root .right = new BTNode (0 );
228
-
229
- BTNode left = root .left ;
230
- BTNode right = root .right ;
231
-
232
- left .left = new BTNode (0 );
233
- left .right = new BTNode (0 );
234
- right .left = new BTNode (0 );
235
- right .right = new BTNode (0 );
236
-
237
- right .right .left = new BTNode (0 );
238
-
239
- left .left .left = new BTNode (0 );
240
-
241
- return tree ;
242
- }
243
-
244
- /**
245
- * Main
246
- */
247
- public static void main (String [] args ) {
248
- // We create a new object to check the binary trees for balance
249
- CheckIfBinaryTreeBalanced balanceCheck = new CheckIfBinaryTreeBalanced ();
250
-
251
- // Build a balanced and unbalanced binary tree
252
- BinaryTree balancedTree = balanceCheck .buildBalancedTree ();
253
- BinaryTree unbalancedTree = balanceCheck .buildUnbalancedTree ();
254
-
255
- // Run basic tests on the algorithms to check for balance
256
- boolean isBalancedRB = balanceCheck .isBalancedRecursive (balancedTree ); // true
257
- boolean isBalancedRU = balanceCheck .isBalancedRecursive (unbalancedTree ); // false
258
- boolean isBalancedIB = balanceCheck .isBalancedIterative (balancedTree ); // true
259
- boolean isBalancedIU = balanceCheck .isBalancedIterative (unbalancedTree ); // false
260
-
261
- // Print the results
262
- System .out .println ("isBalancedRB: " + isBalancedRB );
263
- System .out .println ("isBalancedRU: " + isBalancedRU );
264
- System .out .println ("isBalancedIB: " + isBalancedIB );
265
- System .out .println ("isBalancedIU: " + isBalancedIU );
266
- }
267
155
}
0 commit comments