Refactor BinaryTreeIsBalanced algorithm (#4222)

This commit is contained in:
Albina Gimaletdinova
2023-06-26 17:26:17 +03:00
committed by GitHub
parent 05ca93eace
commit bc699b86e5
3 changed files with 111 additions and 136 deletions

View File

@ -5,9 +5,9 @@ import java.util.Stack;
/**
* This class will check if a BinaryTree is balanced. A balanced binary tree is
* defined as a binary tree where the differenced in height between the left and
* defined as a binary tree where the difference in height between the left and
* right subtree of each node differs by at most one.
*
* <p>
* This can be done in both an iterative and recursive fashion. Below,
* `isBalancedRecursive()` is implemented in a recursive fashion, and
* `isBalancedIterative()` is implemented in an iterative fashion.
@ -15,59 +15,22 @@ import java.util.Stack;
* @author [Ian Cowan](https://github.com/iccowan)
*/
public class CheckIfBinaryTreeBalanced {
/**
* This class implements the BinaryTree for these algorithms
*/
class BinaryTree {
/**
* The root node of the binary tree
*/
BTNode root = null;
}
/**
* This class implements the nodes for the binary tree
*/
class BTNode {
/**
* The value of the node
*/
int value;
/**
* The left child of the node
*/
BTNode left = null;
/**
* The right child of the node
*/
BTNode right = null;
/**
* Constructor
*/
BTNode(int value) {
this.value = value;
}
}
/**
* Recursive is BT balanced implementation
*
* @param binaryTree The binary tree to check if balanced
* @param root The binary tree to check if balanced
*/
public boolean isBalancedRecursive(BinaryTree binaryTree) {
public static boolean isBalancedRecursive(BinaryTree.Node root) {
if (root == null) {
return true;
}
// Create an array of length 1 to keep track of our balance
// Default to true. We use an array so we have an efficient mutable object
// Default to true. We use an array, so we have an efficient mutable object
boolean[] isBalanced = new boolean[1];
isBalanced[0] = true;
// Check for balance and return whether or not we are balanced
isBalancedRecursive(binaryTree.root, 0, isBalanced);
// Check for balance and return whether we are balanced
isBalancedRecursive(root, 0, isBalanced);
return isBalanced[0];
}
@ -76,11 +39,11 @@ public class CheckIfBinaryTreeBalanced {
* recursion. We effectively perform a modified post-order traversal where
* we are looking at the heights of both children of each node in the tree
*
* @param node The current node to explore
* @param depth The current depth of the node
* @param node The current node to explore
* @param depth The current depth of the node
* @param isBalanced The array of length 1 keeping track of our balance
*/
private int isBalancedRecursive(BTNode node, int depth, boolean[] isBalanced) {
private static int isBalancedRecursive(BinaryTree.Node node, int depth, boolean[] isBalanced) {
// If the node is null, we should not explore it and the height is 0
// If the tree is already not balanced, might as well stop because we
// can't make it balanced now!
@ -106,22 +69,26 @@ public class CheckIfBinaryTreeBalanced {
/**
* Iterative is BT balanced implementation
*/
public boolean isBalancedIterative(BinaryTree binaryTree) {
public static boolean isBalancedIterative(BinaryTree.Node root) {
if (root == null) {
return true;
}
// Default that we are balanced and our algo will prove it wrong
boolean isBalanced = true;
// Create a stack for our post order traversal
Stack<BTNode> nodeStack = new Stack<BTNode>();
Stack<BinaryTree.Node> nodeStack = new Stack<>();
// For post order traversal, we'll have to keep track of where we
// visited last
BTNode lastVisited = null;
BinaryTree.Node lastVisited = null;
// Create a HashMap to keep track of the subtree heights for each node
HashMap<BTNode, Integer> subtreeHeights = new HashMap<BTNode, Integer>();
HashMap<BinaryTree.Node, Integer> subtreeHeights = new HashMap<>();
// We begin at the root of the tree
BTNode node = binaryTree.root;
BinaryTree.Node node = root;
// We loop while:
// - the node stack is empty and the node we explore is null
@ -165,7 +132,7 @@ public class CheckIfBinaryTreeBalanced {
}
// The height of the subtree containing this node is the
// max of the left and right subtree heighs plus 1
// max of the left and right subtree heights plus 1
subtreeHeights.put(node, Math.max(rightHeight, leftHeight) + 1);
// We've now visited this node, so we pop it from the stack
@ -182,86 +149,7 @@ public class CheckIfBinaryTreeBalanced {
}
}
// Return whether or not the tree is balanced
// Return whether the tree is balanced
return isBalanced;
}
/**
* Generates the following unbalanced binary tree for testing 0 / \ / \ 0 0
* / / \ / / \ 0 0 0 / \ / \ 0 0 / / 0
*/
private BinaryTree buildUnbalancedTree() {
BinaryTree tree = new BinaryTree();
tree.root = new BTNode(0);
BTNode root = tree.root;
root.left = new BTNode(0);
root.right = new BTNode(0);
BTNode left = root.left;
BTNode right = root.right;
left.left = new BTNode(0);
right.left = new BTNode(0);
right.right = new BTNode(0);
right.left.right = new BTNode(0);
left = left.left;
left.left = new BTNode(0);
left.left.left = new BTNode(0);
left.left.left.left = new BTNode(0);
return tree;
}
/**
* Generates the following balanced binary tree for testing 0 / \ / \ 0 0 /
* \ / \ / 0 / \ 0 0 0 / / / / 0 0
*/
private BinaryTree buildBalancedTree() {
BinaryTree tree = new BinaryTree();
tree.root = new BTNode(0);
BTNode root = tree.root;
root.left = new BTNode(0);
root.right = new BTNode(0);
BTNode left = root.left;
BTNode right = root.right;
left.left = new BTNode(0);
left.right = new BTNode(0);
right.left = new BTNode(0);
right.right = new BTNode(0);
right.right.left = new BTNode(0);
left.left.left = new BTNode(0);
return tree;
}
/**
* Main
*/
public static void main(String[] args) {
// We create a new object to check the binary trees for balance
CheckIfBinaryTreeBalanced balanceCheck = new CheckIfBinaryTreeBalanced();
// Build a balanced and unbalanced binary tree
BinaryTree balancedTree = balanceCheck.buildBalancedTree();
BinaryTree unbalancedTree = balanceCheck.buildUnbalancedTree();
// Run basic tests on the algorithms to check for balance
boolean isBalancedRB = balanceCheck.isBalancedRecursive(balancedTree); // true
boolean isBalancedRU = balanceCheck.isBalancedRecursive(unbalancedTree); // false
boolean isBalancedIB = balanceCheck.isBalancedIterative(balancedTree); // true
boolean isBalancedIU = balanceCheck.isBalancedIterative(unbalancedTree); // false
// Print the results
System.out.println("isBalancedRB: " + isBalancedRB);
System.out.println("isBalancedRU: " + isBalancedRU);
System.out.println("isBalancedIB: " + isBalancedIB);
System.out.println("isBalancedIU: " + isBalancedIU);
}
}