BST

Complete

Succeeds: trees

Summary

Binary search tree(BST)

OperationMethodPerformance
search(v)tree traversal-
insert(v)tree traversal-
remove(v)tree traversal-
  • implements priority queue
  • acts as both a max and min heap simultaneously
OperationMethodPerformance
insert(v)insert into the tree-
extractMax()/extractMin()remove max/min, rebalance-

Inorder traversal

  • left -> self -> right
  • flattening into a sorted array
  • BST sort
java
void inOrder(TreeNode node) {
	if (node == null) return;
	inOrder(node.left);
	// visit the current node
	inOrder(node.right);
}
57638454552373118699010717838

Preorder traversal

  • self -> left -> right
java
void preOrder(TreeNode node) {
	if (node == null) return;
	// visit the current node
	preOrder(node.left);
	preOrder(node.right);
}
57138254653375148679010718839

Postorder traversal

  • left -> right -> self
java
void postOrder(TreeNode node) {
	if (node == null) return;
	postOrder(node.left);
	postOrder(node.right);
	// visit the current node
}
57103855445337211869908717836

Concept

Abstraction

  • BST property
573854537186907183

VisuAlgo’s implementation has support for duplicates by storing the count alongside the value

Data structure

  • pointer to the right and left children
  • (sometimes) pointer to the parent
java
class TreeNode {
	Object data;
	TreeNode left;
	TreeNode right;
}

Catalan number

  • number of unique (unbalanced) tree structures with nodes

Max/min

  • max is the rightmost node
  • min is the leftmost node
  • BSTs can act as both a max and min heap simultaneously

Successor/predecessor

  • with child: successor(6)
  • min (leftmost) of right subtree
632319171213118
  • no children: successor(17)
  • find the parent of the left subtree that the node is in
632319171213118

Removal

632319171213118
6323191712131186323171213118
  • two children: remove(11)
  • replace with successor/predecessor
6323191712131186323191713128

conventionally using the successor

Formal definition of height

Tall trees

18273645h=7h=6h=5h=4h=3h=2h=1h=0

this makes (unbalanced) BSTs not more useful than a linear data structure

Application

Leetcode: Search in a Binary Search Tree

java
public TreeNode searchBST(TreeNode root, int val) {
	if (root == null)
		return null;
	if (root.val == val)
		return root;
	else if (root.val > val)
		return searchBST(root.left, val);
	else
		return searchBST(root.right, val);
}

Leetcode: Minimum Absolute Difference in BST

  • inorder traversal
java
int prev = -1, min = Integer.MAX_VALUE;

public void inOrder(TreeNode root) {
	if (root == null) return;
	inOrder(root.left);
	
	// visit the current node
	if (prev != -1) 
		min = Math.min(min, root.val - prev);
	prev = root.val;
	
	inOrder(root.right);
}

public int getMinimumDifference(TreeNode root) {
	inOrder(root);
	return min;
}

Leetcode: Construct Binary Tree from Preorder and Inorder Traversal

  • build the tree using preorder traversal
  • for each subtree, slice the inorder array to build its left and right subtrees
java
int i = 0;
Map<Integer, Integer> mp = new HashMap<>();
int[] pre;

public TreeNode build(int s, int e) {
	if (s > e)
		return null;
	
	int val = pre[i++];
	TreeNode root = new TreeNode(val);

	int idx = mp.get(val);
	root.left = build(s, idx - 1);
	root.right = build(idx + 1, e);
	
	return root;
}

public TreeNode buildTree(int[] preorder, int[] inorder) {
	pre = preorder;
	for (int i = 0; i < inorder.length; i++)
		mp.put(inorder[i], i);

	return build(0, inorder.length - 1);
}

Leetcode: Delete Node in a BST

java
public TreeNode deleteNode(TreeNode root, int key) {
	if (root == null)
		return null;
	if (root.val == key) { // found the target
		if (root.left == null && root.right == null) // if no children, just delete it
			return null;
		else if (root.left != null && root.right == null) // has left child only
			return root.left;
		else if (root.left == null && root.right != null) // has right child only
			return root.right;
		else {
			TreeNode succ = root.right; // find the successor of the current node, predecessor will work too
			while (succ.left != null) 
				succ = succ.left;
			root.val = succ.val; // replace the current value with the successor
			root.right = deleteNode(root.right, succ.val); // delete the successor recursively
			return root;
		}
	} else if (root.val > key) {
		root.left = deleteNode(root.left, key);
		return root;
	} else {
		root.right = deleteNode(root.right, key);
		return root;
	}
}