Master advanced Binary Search Tree operations with a focus on efficient searching and traversal techniques.
Building on the fundamentals from Binary Trees I, we'll explore advanced searching techniques and tree traversal methods. Learn how to efficiently search for values, implement different traversal orders, and understand their applications.
Create a recursive search method that leverages the BST property
public boolean search(int value) {
return searchRecursive(root, value);
}
private boolean searchRecursive(Node node, int value) {
// Base case: Empty tree or value found
if (node == null) {
return false;
}
if (node.getValue() == value) {
return true;
}
// Recursive case: Search left or right subtree
if (value < node.getValue()) {
return searchRecursive(node.getLeft(), value);
} else {
return searchRecursive(node.getRight(), value);
}
}
Create a method to traverse the tree in-order (left, root, right)
public void inOrderTraversal() {
inOrderTraversalHelper(root);
}
private void inOrderTraversalHelper(Node node) {
if (node == null) {
return;
}
// Visit left subtree
inOrderTraversalHelper(node.getLeft());
// Visit current node
System.out.print(node.getValue() + " ");
// Visit right subtree
inOrderTraversalHelper(node.getRight());
}
Create methods for the other common traversal patterns
public void preOrderTraversal() {
preOrderTraversalHelper(root);
}
private void preOrderTraversalHelper(Node node) {
if (node == null) {
return;
}
// Visit current node first
System.out.print(node.getValue() + " ");
// Then visit subtrees
preOrderTraversalHelper(node.getLeft());
preOrderTraversalHelper(node.getRight());
}
public void postOrderTraversal() {
postOrderTraversalHelper(root);
}
private void postOrderTraversalHelper(Node node) {
if (node == null) {
return;
}
// Visit subtrees first
postOrderTraversalHelper(node.getLeft());
postOrderTraversalHelper(node.getRight());
// Visit current node last
System.out.print(node.getValue() + " ");
}
Let's visualize how search works in a BST. Consider searching for the value 7 in this tree:
10
/ \
5 15
/ \ / \
3 7 12 17
7 < 10, so go left
7 > 5, so go right
7 == 7, found the target value! Return true.
For the tree above:
For better space efficiency, you can implement search and traversals iteratively using a stack:
public boolean searchIterative(int value) {
Node current = root;
while (current != null) {
if (current.getValue() == value) {
return true;
}
if (value < current.getValue()) {
current = current.getLeft();
} else {
current = current.getRight();
}
}
return false;
}
public void inOrderIterative() {
if (root == null) return;
Stack stack = new Stack<>();
Node current = root;
while (current != null || !stack.isEmpty()) {
// Go left as far as possible
while (current != null) {
stack.push(current);
current = current.getLeft();
}
// Process the node
current = stack.pop();
System.out.print(current.getValue() + " ");
// Go right
current = current.getRight();
}
}
In a BST, finding the in-order predecessor or successor of a node can be useful for many operations:
public Node findSuccessor(Node node) {
// If right subtree exists, find the minimum value in it
if (node.getRight() != null) {
return findMin(node.getRight());
}
// Otherwise, find the nearest ancestor where node is in its left subtree
Node successor = null;
Node current = root;
while (current != null) {
if (node.getValue() < current.getValue()) {
successor = current;
current = current.getLeft();
} else if (node.getValue() > current.getValue()) {
current = current.getRight();
} else {
break; // Found the node
}
}
return successor;
}
private Node findMin(Node node) {
while (node.getLeft() != null) {
node = node.getLeft();
}
return node;
}
Implement a search method that returns true if a value exists in the BST, false otherwise.
public boolean search(int value) {
// Your implementation here
}
Implement in-order traversal to print all values in ascending order.
public void inOrderTraversal() {
// Your implementation here
}
Implement level-order (breadth-first) traversal to visit all nodes level by level.
public void levelOrderTraversal() {
if (root == null) return;
Queue queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
// Your implementation here
// Hint: Use a queue data structure
}
}
Write a method to count the total number of nodes in the BST.
public int countNodes() {
// Your implementation here
// Hint: Can use any traversal method
}
Implement a method to find the lowest common ancestor (LCA) of two nodes in the BST.
public Node findLCA(int value1, int value2) {
// Your implementation here
// Hint: Use the BST property to determine which subtree to search
}
Implement the delete operation for a BST. This is more complex than insertion or search.
public void delete(int value) {
root = deleteRecursive(root, value);
}
private Node deleteRecursive(Node root, int value) {
// Your implementation here
// Cases to handle:
// 1. Node is a leaf
// 2. Node has one child
// 3. Node has two children (find in-order successor)
}