binary search trees cmput 115 - lecture 23 department of computing science university of alberta...
Post on 19-Dec-2015
214 views
TRANSCRIPT
Binary Search TreesBinary Search Trees
Cmput 115 - Lecture 23
Department of Computing Science
University of Alberta©Duane Szafron 2000
Some code in this lecture is based on code from the book:Java Structures by Duane A. Bailey or the companion structure package
Revised 3/19/00
©Duane Szafron 2000
2
LAB EXAM NEXT WEEK!LAB EXAM NEXT WEEK!
Start on Monday!
Please read information on CMPUT 115 website.
©Duane Szafron 2000
3
About This LectureAbout This Lecture
In this lecture we study an implementation of OrderedStructure called the BinarySearchTree.
NOTE: We will not be discussing Huffman coding, priority queues, or heap sort.
©Duane Szafron 2000
4
OutlineOutline Revisit OrderedStructure Binary Search Tree Definition Binary Search Tree Implementation Unbalanced and Balanced Binary Search
Trees
©Duane Szafron 2000
5
Re-visiting OrderedStructuresRe-visiting OrderedStructures
We have two implementations of the OrderedStructure interface: OrderedVector and OrderedList.
For OrderedVector– The time for finding an element is O(log n) comparisons due to
a binary search.– The time for adding or removing an element is O(log n)
comparisons to find it and O(n) assignments to “move” existing elements to the right of it.
For OrderedList– The time for finding an element is O(n) comparisons due to a
sequential search.– The time for adding or removing an element is O(n)
comparisons to find it and O(C) assignments to fix links.
©Duane Szafron 2000
6
Binary Search TreeBinary Search Tree We want to combine the advantage of a binary search
with the advantage of just fixing a few links during adding and removal to obtain an implementation called a BinarySearchTree where:– The time for finding an element is O(log n) comparisons due
to a binary search.– The time for adding or removing an element is O(log n)
comparisons to find it and O(C) assignments to fix links.
A binary search tree (BST) is a binary tree in which every element is greater than or equal to all elements in the left sub-tree of the node containing that element and is less than or equal to all elements in the right sub-tree of the node containing that element.
©Duane Szafron 2000
7
Sort Order in BinarySearchTreesSort Order in BinarySearchTrees Many different BSTs can be formed from the same
set of elements.
40
20
10 30
60
50 70
70
50
10 60
30
20 40
70
50
40 60
20
10 30
40
10
30
20
50
70
60
However, an inorder traversal always produces the elements in sorted order: 10, 20, 30, 40, 50, 60, 70.
©Duane Szafron 2000
8
OrderedStructure HierarchyOrderedStructure Hierarchy The structure package adds BinarySearchTree
as another implementation of OrderedStructure.
Store
Collection
OrderedStructure
OrderedVector OrderedList BinarySearchTree
©Duane Szafron 2000
9
Structure Interface - StoreStructure Interface - Store
public interface Store {public int size();//post: returns the number of elements contained in // the store.
public boolean isEmpty();// post: returns the true iff store is empty.
public void clear();// post: clears the store so that it contains no // elements.
}
code based on Bailey pg. 18
©Duane Szafron 2000
10
Structure Interface - CollectionStructure Interface - Collectionpublic interface Collection extends Store {
public boolean contains(Object anObject);// pre: anObject is non-null// post: returns true iff the collection contains the object
public void add(Object anObject);// pre: anObject is non-null// post: the object is added to the collection. The // replacement policy is not specified
public Object remove(Object anObject);// pre: anObject is non-null// post: removes object “equal” to anObject and returns it,// otherwise returns nil
public Iterator elements();// post: return an iterator for traversing the collection
} code based on Bailey pg. 19
©Duane Szafron 2000
11
Structure Interface - OrderedStructureStructure Interface - OrderedStructure
public interface OrderedStructure extends Collection
{}
code based on Bailey pg. 173
©Duane Szafron 2000
12
Recall OrderedStructure ExampleRecall OrderedStructure Example
public static void main(String[ ] args) {
OrderedStructure container;RandomInt generator;int index;Iterator iterator;
container = new BinarySearchTree();generator = new RandomInt(1);for (index = 0; index < 100; index++) {
container.add(new Integer(generator.next(100)));iterator = container.elements();while(iterator.hasMoreElements())
System.out.print(iterator.nextElement() + ‘ ‘);}
code based on Bailey pg. 158
1 1 1 2 2 3 3 3 44 5 7 7 7 8 9 9 1013 13 14 14 15 17...
indexOfpreviousOf
©Duane Szafron 2000
13
Implementation of BSTImplementation of BST
The implementation of a BinarySearchTree parallels the implementation of a BinaryTree.
However, addition and removal of elements is different since we don’t provide the user with a cursor to specify location.
Instead the element must be added or removed at the correct location at the discretion of our implementation based on the order of the node.
©Duane Szafron 2000
14
BST - BST - State and ConstructorState and Constructor
class BinarySearchTree implements OrderedStructure {
protected BinaryTreeNode root;protected int count;
public BinarySearchTree() {// post: constructs an empty binary search tree.
this.root = null;this.count = 0;
}
code based on Bailey pg. 252
©Duane Szafron 2000
15
BST - BST - Store InterfaceStore Interface
/* Interface Store Methods */public int size() {//post: returns the number of elements in the store.
return this.count;}
public boolean isEmpty() {// post: returns the true iff store is empty.
return this.size() == 0; // return this.root == null}
public void clear();// post: clears the store so that it contains no elements.
this.root = null;this.count = 0;
}code based on Bailey SPackage
©Duane Szafron 2000
16
Searching for an Element in a BSTSearching for an Element in a BST
To implement contains(Object), add(Object) and remove(Object) we must first search for the object we are looking for.
In contains(Object), we are done when we either find Object or ensure it is not in the tree.
In add(Object), the search determines not only whether Object is there or not, but the specific location where it belongs. We can use this information to add it.
In remove(Object), the search determines not only whether it is there or not, but the specific location where it is, since we need this information to remove it.
©Duane Szafron 2000
17
The Location of an Element in a BSTThe Location of an Element in a BST
We use a locate method that returns either the node that contains the element or the parent node of the node where the element should be added as a new leaf:
– Compare the element to the root element.
– If they are equal return the root node.
– If element > root then recursively search the right sub-tree.
– Otherwise, recursively search the left sub-tree.
– If the sub-tree to be searched is null, return the root.
Search for 30: 50, 20, 30, return 30Search for 5 or 15: 50, 20, 10, return 10Search for 25: 50, 20, 30, return 30Search for 75: 50, 70, return 70
50
20
10 30
70
60
40
©Duane Szafron 2000
18
BST - BST - locate(BinaryTreeNode, Object) 1locate(BinaryTreeNode, Object) 1
/* Protected Methods */protected BinaryTreeNode locate(BinaryTreeNode root,
Object anObject) {// pre: root and anObject are non-null// post: returns an existing tree node containing an Object// equal to the given one or the parent node where the
// object should be inserted as a child if not found.
BinaryTreeNode child;int compare;rootElement = (Comparable) this.root.value();compare = anObject.compareTo((Comparable)this.root.value());
if (compare == 0)return root;
code based on Bailey pg. 252
©Duane Szafron 2000
19
BST - BST - locate(BTN, Object)locate(BTN, Object)
else if (compare < 0)child = root.left();
elsechild = root.right();
if (child == null)return root;
elsereturn this.locate(child, anObject);
}
code based on Bailey pg. 252
©Duane Szafron 2000
20
BST - BST - contains(Object)contains(Object)
/* Interface Collection Methods */public boolean contains(Object anObject) {// pre: anObject is non-null// post: returns true iff the collection contains the object
BinaryTreeNode possibleNode;
if (this.root == null)
return false;
possibleNode =
this.locate(this.root,(Comparable)anObject);
return anObject.equals(possibleNode.value());
}
code based on Bailey pg. 253
©Duane Szafron 2000
21
Adding an Element to a BSTAdding an Element to a BST An element is always added in a new leaf node. We start with a call to locate(BTN, Object). There are two cases:
– The element is not already in the tree. Insert it as the appropriate child of the parent node returned from locate.
– The element is already in the tree. If the left child of that node is empty, insert it there. If it is full, insert it as the right child of the predecessor of the found node.
50
20
10 30
70
60
40
Add 5: locate 10, insert leftAdd 15: locate 10, insert rightAdd 75: locate 70, insert rightAdd 30: locate 30, insert leftAdd 50: locate 50, find predecessor 40, insert right
5
50
15
75
30
©Duane Szafron 2000
22
Finding the Predecessor in a BSTFinding the Predecessor in a BST
To find the predecessor of an element in a Binary Search Tree that has a left child:– Go left once– Go right until there is no right child.
50
20
10 30
70
60
40
Predecessor of 50: left 20, right 30, right 40Predecessor of 70: left 60Predecessor of 30: no left child, can’t use this algorithm
©Duane Szafron 2000
23
BST - BST - predecessor(BinaryTreeNode)predecessor(BinaryTreeNode)
/* Protected Methods */protected BinaryTreeNode
predecessor(BinaryTreeNode root) {// pre: root is non-null and root has a left child// post: returns node whose element is just before the root// node in the order.
BinaryTreeNode predecessor;
predecessor = root.left();while (predecessor.right() != null)
predecessor = predecessor.right();return predecessor;
}
code based on Bailey pg. 254
©Duane Szafron 2000
24
5 15
Alternative Strategy for AddAlternative Strategy for Add The previous strategy always inserts duplicate elements in the right sub-tree.
Alternatively, we could always insert duplicate elements in the left sub-tree by finding the successor of the found node and inserting to the left.
50
20
10 30
70
60
40
Add 5: locate 10, insert leftAdd 15: locate 10, insert rightAdd 75: locate 70, insert rightAdd 30: locate 30, find successor 40, insert leftAdd 50: locate 50, find successor 60, insert left
75
30
50
©Duane Szafron 2000
25
BST - BST - add(Object) 1add(Object) 1
public void add(Object anObject);// pre: anObject is non-null// post: the object is added at the appropriate position // based on comparing it to the other elements.
BinaryTreeNode newNode;BinaryTreeNode insertionNode;Comparable newElement;Comparable nodeElement;newNode = new BinaryTreeNode(val);
// if there's no root, add element at root.if (this.root == null)
this.root = newNode;else {
newElement = (Comparable) anObject;insertionNode = locate(root, newElement);
code based on Bailey pg. 253
©Duane Szafron 2000
26
BST - BST - add(Object)add(Object)
nodeElement = (Comparable) insertionNode.value(); if (nodeElement.compareTo(newElement) < 0) insertionNode.setRight(newNode); else if (insertionNode.left() != null)
// element is already in tree and left node is not open
this.predecessor(insertionNode).setRight(newNode); else insertionNode.setLeft(newNode);
}count++;
}
code based on Bailey pg. 253
See slide 23 for implementation of predecessor
©Duane Szafron 2000
27
Removing from a BST - easyRemoving from a BST - easy To remove an element in a leaf node, simply remove the
leaf node.
If the element is in a node that is not a leaf node it has one or two sub-trees.
If it has one sub-tree, remove the node and replace it by its single sub-tree.
50
B
A A
B50
A
B
A
B
©Duane Szafron 2000
28
Removing from a BST - harderRemoving from a BST - harder If the element is in a node with two sub-trees, but the
left child has no right sub-tree, remove the node containing the element and replace it by the left child.
50
A
B
C40
40
A
B C
©Duane Szafron 2000
29
RemovingRemoving from a BST - from a BST - hardest 1hardest 1
If the element is in a node with two sub-trees, and the left child has a right sub-tree, find the predecessor of the node containing the element to be removed, by going left once and then right as many times as possible.
Note that the predecessor cannot have a right sub-tree or it would not have been the predecessor.
50
A
B
C20
30
D40
E
©Duane Szafron 2000
30
Removing from a BST - hardest 2Removing from a BST - hardest 2
Replace the predecessor node by its left sub-tree.
Remove the node containing the element and replace it by the predecessor node.
50
A
B
C20
30
D40
E
40
A
B
C20
30
D E
©Duane Szafron 2000
31
BST - BST - remove(Object) 1remove(Object) 1
public Object remove(Object anObject);// pre: anObject is non-null// post: removes object “equal” to anObject and returns it,// otherwise returns nil
Comparable element;BinaryTreeNode newRoot;BinaryTreeNode removeNode;Object result;element = (Comparable)anObject;if (this.isEmpty())
return null;if (element.equals(this.root.value())) {
newroot = removeTop(this.root);count--;result = this.root.value();this.root = newroot;return result;
} code based on Bailey SPackage
©Duane Szafron 2000
32
BST - BST - remove(Object) 2remove(Object) 2
removeNode = locate(root, element);if (element.equals(removeNode.value())) {
count--;parent = removeNode.parent();if (parent.right() == removeNode) parent.setRight(removeTop(removeNode));else parent.setLeft(removeTop(removeNode));
return removeNode.value();}return null;
}
code based on Bailey SPackage
©Duane Szafron 2000
33
BST - BST - removeTop(BTN) 1removeTop(BTN) 1
protected BinaryTreeNode removeTop(BinaryTreeNode topNode) {// pre: tree is not empty.// post: root of tree (topNode) is disconnected from tree // and a new root is returned, new root has no parent.BinaryTreeNode left;BinaryTreeNode right;BinaryTreeNode predecessor;BinaryTreeNode parent;left = topNode.left();right = topNode.right();// disconnect top nodetopNode.setLeft(null);topNode.setRight(null);// Easy case: only one sub-treeif (left == null)
return right;code based on Bailey pg. 256
©Duane Szafron 2000
34
BST - BST - removeTop(BTN) 2removeTop(BTN) 2if (right == null)
return left;predecessor = left.right();// Harder case: left node has no right sub-treeif (predecessor == null) {
left.setRight(right);return left;
}// Hardest case: left node has a right sub-treeparent = left;while (predecessor.right() != null) {
parent = predecessor;predecessor = predecessor.right();
}parent.setRight(predecessor.left());predecessor.setLeft(left);predecessor.setRight(right);
return predecessor;} code based on Bailey pg. 256
©Duane Szafron 2000
35
BST - BST - elements()elements()
public Iterator elements();// post: return an iterator for traversing the collection
return new BRInorderIterator (this.root);}
code based on Bailey pg. 257
©Duane Szafron 2000
36
Efficiency of Binary Search TreesEfficiency of Binary Search Trees
Each of the time consuming operations is O(h), where h is the height of the tree.
If the tree is fairly balanced, h = log n so the operations are O(log n).
However, since many binary trees can be made from the same elements, we could be unlucky when we make our tree and have a tree with height h = n, which is essentially a linked list and the search time is O(n).
What insertion orders cause problems?
©Duane Szafron 2000
37
Unbalanced Binary Search Trees 1Unbalanced Binary Search Trees 1 Look at a tree with insertion order: 10, 20, 30, 40:
if (nodeElement.compareTo(newElement) < 0)insertionNode.setRight(newNode);
else if (insertionNode.left() != null)// element is already in tree and left node is not open
this.predecessor(insertionNode).setRight(newNode);else
insertionNode.setLeft(newNode);
10
20
10
30
20
10
40
30
20
10
©Duane Szafron 2000
38
Unbalanced Binary Search Trees 2Unbalanced Binary Search Trees 2
40
30
40
20
30
40
10
20
30
40
Look at a tree with insertion order: 40, 30, 20, 10:
if (nodeElement.compareTo(newElement) < 0)insertionNode.setRight(newNode);
else if (insertionNode.left() != null)// element is already in tree and left node is not open
this.predecessor(insertionNode).setRight(newNode);else
insertionNode.setLeft(newNode);
©Duane Szafron 2000
39
Balanced Binary Search TreesBalanced Binary Search Trees Look at a tree with insertion order: 30, 20, 40, 10, 30:
if (nodeElement.compareTo(newElement) < 0)insertionNode.setRight(newNode);
else if (insertionNode.left() != null)// element is already in tree and left node is not open
this.predecessor(insertionNode).setRight(newNode);else
insertionNode.setLeft(newNode);
30
20
30
40
10
20
30
4020
30
10
4020
30
30