binary search trees cmput 115 - lecture 23 department of computing science university of alberta...

39
Binary Search Trees Binary 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

Post on 19-Dec-2015

214 views

Category:

Documents


0 download

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