CS 231 Spring 2018

Binary Search - A binary is a sorted (tree node can contain a key value pair) in which the key field value of the root node is greater than the key field values of all of the nodes in the root’s left subtree, and less than key field values of all of the nodes in the root’s right subtree. In addition, each subtree in the tree is also a binary search tree.

- Example:

• The value of the key field of the tree’s root node, 50, is greater than all the keys in its left subtree (40, 35, 47, 43), and it is also less than all the keys in its right subtree (63, 55, 70, 68, 80). • In addition, all subtrees in the tree are also binary trees, which can be verified by inspecting them. • For example, consider the subtree whose root node is 63. This subtree is also a binary search tree because all keys in 63’s left subtree (55) are less than 63, and all of the keys in the root’s right subtree (70, 68, and 80) are greater than 63.

- BST combines the flexibility of insertion in linked lists with the efficiency of search in an ordered array.

- Binary Search Tree Operations • Add • Search • Remove

/** * Ying Li * KeyValuePair.java CS 231 Spring 2018

* 03/28/2018 */ public class KeyValuePair { private K key; private V value;

public KeyValuePair (K k, V v) { key = k; value = v; }

public K getKey () { return key; }

public V getValue () { return value; }

public void setValue (V v) { value = v; }

public String toString () { return "(" + key + ", " + value + ")"; } }

/** * Ying Li * BST.java * 03/28/2018 */ import java.util.Comparator;

/* BST class */ public class BST { private TreeNode root; private Comparator comparator;

public BST (Comparator comp) { root = null; comparator = comp; }

public void add (K k, V v) { if (root == null) root = new TreeNode (k, v, null, null); else root.add(k, v, comparator); }

public void traverse () { if (root == null) System.out.println("Empty tree!"); else root.traverse(); }

public V search (K key) { if (root == null) return null; return root.search(key, comparator); }

public TreeNode remove (K key) { if (root == null) return null; return root.remove(key, root, comparator); }

public static void main (String[] args) { System.out.println("Create a tree"); BST tree = new BST(new AscendingStringComparator()); tree.add("e", 5); CS 231 Spring 2018

tree.add("", 3); tree.add("h", 8); tree.add("b", 2); tree.add("d", 4); tree.add("g", 7); tree.add("f", 6); tree.add("a", 1); tree.add("i", 9); System.out.println("In-order traverse the tree"); tree.traverse(); System.out.println("The value associated with e is " + tree.search("e")); tree.remove("a"); System.out.println("In-order traverse the tree after removing 'a'"); tree.traverse(); tree.remove("i"); System.out.println("In-order traverse the tree after removing 'i'"); tree.traverse(); tree.remove("e"); System.out.println("In-order traverse the tree after removing 'e'"); tree.traverse(); } }

/* Tree Node class */ class TreeNode { private KeyValuePair pair; private TreeNode left; private TreeNode right;

public TreeNode (K k, V v, TreeNode l, TreeNode r) { pair = new KeyValuePair (k, v); left = l; right = r; }

public void add (K key, V val, Comparator comp) { if (comp.compare(key, pair.getKey()) == 0) pair.setValue(val); else if (comp.compare(key, pair.getKey()) < 0) { if (left == null) left = new TreeNode (key, val, null, null); else left.add(key, val, comp); } else { if (right == null) right = new TreeNode (key, val, null, null); else right.add(key, val, comp); } }

public void traverse () { if (left != null) left.traverse(); System.out.println(pair); if (right != null) right.traverse(); }

public V search (K key, Comparator comp) { int compRslt = comp.compare(key, pair.getKey());

if (compRslt == 0) return pair.getValue(); else if (compRslt < 0) { if (left == null) return null; else return left.search(key, comp); } else { if (right == null) return null; CS 231 Spring 2018

else return right.search(key, comp); } }

public TreeNode remove (K key, TreeNode node, Comparator comp) { if (node == null) return null; else if (comp.compare(key, node.pair.getKey()) < 0) node.left = remove(key, node.left, comp); else if (comp.compare(key, node.pair.getKey()) > 0) node.right = remove(key, node.right, comp); else node = removeNode(node, comp);

return node; }

private TreeNode removeNode (TreeNode node, Comparator comp) { if (node.left == null) return node.right; else if (node.right == null) return node.left; else { KeyValuePair p = getPredecessor(node.left); node.pair = p; node.left = remove(p.getKey(), node.left, comp); return node; } }

private KeyValuePair getPredecessor (TreeNode subtree) { TreeNode tmp = subtree; while (tmp.right != null) { tmp = tmp.right; } return tmp.pair; } }

/* Comparator class */ class AscendingStringComparator implements Comparator { public int compare (String s1, String s2) { return s1.compareTo(s2); } } removeNode (node, comp) : returns TreeNode if (node.left is null) AND (node.right is null) return null else if node.left is null return node.right else if node.right is null return node.left else Find predecessor node.pair = predecessor.pair node.left = remove(predecessor.pair.key, node.left) return node

Method remove(key, node, comp) return TreeNode Definition: Removes node with key from tree rooted at node CS 231 Spring 2018

Base case 1: If key is not in the tree (node is null), return null Base case 2: If key matches node’s key, remove node General case: If key < node.pair.key, return remove(key, node.left.comp) else return remove(key.node.right.comp)

REF: Object-Oriented Data Structures using Java 4th edition, Nell Dale, Daniel T. Joyce, Chip Weems Disclaimer: Notes adapted from previous CS 231 lecture materials at Colby College.