150 likes | 251 Views
Binary Search Trees. Wellesley College CS230 Lecture 19 Thursday, April 12 Handout #30. PS5 due 11:59pm Wednesday, April 18 Final Project Phase 2 (Program Outline) due 1:30pm Tuesday, April 24. Overview of Today’s Lecture. Review of Binary Search Trees (BSTs)
E N D
Binary Search Trees Wellesley College CS230 Lecture 19 Thursday, April 12 Handout #30 PS5 due 11:59pm Wednesday, April 18 Final Project Phase 2 (Program Outline) due 1:30pm Tuesday, April 24
Overview of Today’s Lecture • Review of Binary Search Trees (BSTs) • Searching, Insertion, and Deletion in BSTs • Implementing Sets, Bags, Tables using BSTs
Binary Search Trees To get full advantage of binary trees for data structures, need the values to be ordered. A binary search tree (BST) is a binary tree in which the following BST properties hold at every node:(1) All elements in the left subtree are ≤ the value; (2) All elements in the right subtree are ≥ the value. Here is a sample BST: P • Notes: • A BST may contain duplicates • The in-order traversal of BST elements yields them in sorted order. E.g.: C F F J M P S V • For n > 1, there is more than one BST with n elements. F S C M V F J
Predecessors and Succesors The predecessor of a node N is the node that immediately precedes N in an in-order traversal of the tree (or null if no such node exists). E.g., the predecessor of node P is node M, of node M is node J, and of node J is node F. The successor of a node is the node N that immediately follows N in an in-order traversal of the tree (or null if no such node exists). E.g., the successor of node F is node J, of node J is node M, and of node M is node P. P F S C M V F J
An MBST<T> Class import java.util.*; // import Comparator, Iterator public class MBST<T> { private static MBinTree MBT; // Local abbreviation for MBinTree // Instance Variables private Comparator<T> comp; private MBinTree<T> elts; // Constructor Methods // Constructor that supplies explicit Comparator public MBST (Comparator<T> comp) { this.comp = comp; elts = MBT.<T>leaf(); } // Constructor without an explicit Comparator uses null // as the Comparator. public MBST () { this(null); } … other methods go here … }
Comparisons in MBST<T> // Instance methods public Comparator<T> comparator() { return comp; } // Method uses for all comparisons. Use the explicit Comparator comp // if it's non-null; otherwise, assume T extends Comparable<T> and // use the compareTo method of an element. private int compare (T x, T y) { if (comp != null) { return comp.compare(x,y); } else { // Note: the cast here will generate a warning in Java 1.5 // because the cast can fail at run-time for a non-Comparable x. return ((Comparable<T>) x).compareTo(y); } }
Searching in MBST<T> /** Return true if x is in the tree and false otherwise */ public boolean search (T x) { MBinTree<T> here = elts; while (! MBT.isLeaf(here)) { int c = compare(x, MBT.value(here)); if (c == 0) { return true; } else if (c < 0) { here = MBT.left(here); } else { here = MBT.right(here); } } // Only reach here if got to leaf without finding element: return false; }
Insertion in MBST<T> public void insert (T x) { MBinTree<T> child = elts; MBinTree<T> parent = null; // parent of child boolean isChildToLeft = true; // is child the left of parent? (initialized arbitrarily) while (! MBT.isLeaf(child)) { // search for insertion point int c = compare(x, MBT.value(child)); if (c == 0) throw new MBSTInsertionException(child); // element is already in tree else if (c < 0) { parent = child; child = MBT.left(child); isChildToLeft = true; } else { parent = child; child = MBT.right(child); isChildToLeft = false; } } // Only reach here if got to leaf without finding element: // Replace the leaf in parent by a new node: MBinTree<T> newNode = MBT.node(MBT.<T>leaf(), x, MBT.<T>leaf()); setChild(parent, isChildToLeft, newNode); }
Setting the Child private void setChild (MBinTree<T> parent, boolean isChildToLeft, MBinTree<T> newChild) { if (parent == null) { // special case when no parent elts = newChild; } else if (isChildToLeft) { MBT.setLeft(parent, newChild); } else { MBT.setRight(parent, newChild); } }
Deletion In MBST<T> public boolean delete (T x) { MBinTree<T> child = elts; MBinTree<T> parent = null; // parent of child boolean isChildToLeft = true; // is child the left of parent? (initialized arbitrarily) while (! MBT.isLeaf(child)) { // search for insertion point int c = compare(x, MBT.value(child)); if (c == 0) { deleteNode(parent, child, isChildToLeft); // See next slide return true; // element is in tree. } else if (c < 0) { parent = child; child = MBT.left(child); isChildToLeft = true; } else { parent = child; child = MBT.right(child); isChildToLeft = false; } } // Only reach here if got to leaf without finding element. return false; // element not in tree. }
deleteNode() // Delete a non-leaf child from (possibly null) parent private void deleteNode (MBinTree<T> parent, MBinTree<T> child, boolean isChildToLeft) { // Easy cases are if one subtree of child is a leaf. if (MBT.isLeaf(MBT.left(child))) { setChild(parent, isChildToLeft, MBT.right(child)); } else if (MBT.isLeaf(MBT.right(child))) { setChild(parent, isChildToLeft, MBT.left(child)); } else { // Hard case is if neither subtree of child is a leaf. // In this case delete predecessor and replace // child's value by predecessor's value T predecessorValue = deletePredecessor(child); // See next slide // predecessorValue is guaranteed to be non-null in this case, // since only get here if MBT.left(child) is not a leaf. MBT.setValue(child, predecessorValue); } }
deletePredecessor() // Deletes the predecessor of this node and returns its value. // Returns null if there is no predecessor private T deletePredecessor (MBinTree<T> node) { if (MBT.isLeaf(MBT.left(node))) { return null; // No predecessor; return null } else { MBinTree<T> parent = node; MBinTree<T> child = MBT.left(node); boolean isChildToLeft = true; while (!(MBT.isLeaf(MBT.right(child)))) { // Find the predecessor node = rightmost node to the left of given node parent = child; child = MBT.right(child); isChildToLeft = false; } deleteNode(parent, child, isChildToLeft); // delete predecessor node // Since right of child is a leaf, this will use "easy" case of deleteNode(); return MBT.value(child); // return value in predecessor node } }
Abstracting over BST search: FindInfo public class FindInfo<T> { public MBinTree<T> parent, child; public boolean isChildToLeft; public FindInfo (MBinTree<T> parent, MBinTree<T> child, boolean isChildToLeft) { this.parent = parent; this.child = child; this.isChildToLeft = isChildToLeft; } }
Abstracting over BST search: find() /** If x exists in tree returns a FindInfo fi where: + fi.child is the node containing x; + fi.parent is the parent of child (or null if there is no parent); + fi.isChildToLeft is true if child is to the left of parent (or there is none); else false If x does not exist in the tree, returns a FindInfo fi where: + fi.child is the leaf where x would be inserted into the tree. + fi.parent is the node below which x would be inserted into the tree. + fi.isChildToLeft is true if x would be inserted to the left of fei.parent; else false */ public FindInfo<T> find (T x) { MBinTree<T> child = elts; MBinTree<T> parent = null; // parent of child boolean isChildToLeft = true; // is child the left of parent? (initialized arbitrarily) int c = 0; // result of comparison (initialized arbitrarily) while (!MBT.isLeaf(child) && // stuff result of comparison in variable c !((c = compare(x, MBT.value(child))) == 0)) { if (c < 0) {parent = child; child = MBT.left(child); isChildToLeft = true;} else {parent = child; child = MBT.right(child); isChildToLeft = false;} } return new FindInfo<T>(parent, child, isChildToLeft); }
Abstracted search(), insert(), delete() public boolean search (T x) { return (!MBT.isLeaf(find(x).child)); } public void insert (T x) { FindInfo<T> fi = find(x); if (MBT.isLeaf(fi.child)) { MBinTree<T> newNode = MBT.node(MBT.<T>leaf(), x, MBT.<T>leaf()); setChild(fi.parent, fi.isChildToLeft, newNode); } else { throw new MBSTInsertionException(fi.child); // element is already in tree } } public boolean delete (T x) { FindInfo<T> fi = find(x); if (!MBT.isLeaf(fi.child)) { deleteNode(fi.parent, fi.child, fi.isChildToLeft); return true; // element is in tree } else { return false; // element not in tree. } }