file: 06.1.PriorityQueuesBinaryTreesAndHeaps.txt author: Bob Muller date: February 18, 2014 CS102 Computer Science II Lecture Notes for week 6 Tuesday February 18, 2014 ---------------------------------------------------------------------- Topics: 1. Review 2. Ordered Points and Lines 3. Priority Queues 4. Binary Trees 5. Binary Heaps 6. Mutation ---------------------------------------------------------------------- 1. Review: Last time we talked about sets, relations and orders. We did this because many important ways to structure data require the ability to -compare- the items that are stored in the structure. The bottom line was this: Let X be a set and let R be a relation on X (i.e., R is a subset of X x X). R is a -partial order- on X, if R is 1. reflexive, 2. anti-symmetric and 3. transitive. We usually write x <=_R y rather than (x, y) in R. Or if R is understood, we just write x <= y. We sometimes say that X is an ordered set without mentioning R if R is understood. But remember that for a given set X there can be many different partial orders R0, R1, ... . A partial order R of set X is a -total order- if for each x, y in X, either x <= y or y <= x in R. A total order is sometimes called a -chain-. In Java, total orders are codified in the Comparable interface. ---------------------------------------------------------------------- 2. Ordered Points and Lines Code See http://www.cs.bc.edu/~muller/teaching/cs102/s14/dist/code/ 05.2.ordersAndComparability.zip ---------------------------------------------------------------------- 3. Priority Queues A queue is a FIFO structure, the first item inserted is the first one removed. It's sometimes desirable to be able to maintain a queue in which insertion and removal are sensitive to a priority. Of course, this will require is to be able to -compare- the priorities of items in the queue. Example: A min PQ containing letters with a priority of alphabetical ordering. Operation PQ (front left) empty insert(F) F insert(L) F L insert(C) C F L remove() F L smallest C is out insert(G) F G L ------------------------- An API for a Max Priority Queue: public interface MaxPQ> { public void insert(Key v); public Key max(); public Key delMax(); public boolean isEmpty(); public int size(); } NOTE: the notation for the type parameter > means that ------------------------------------------- Thinking about possible implementations: - a sequential resizing array implementation would -seem- a poor choice because the insert operation would seem to require linear complexity and would require shifting items around in the array, - a linked implementation could work but the complexity of the insert operation would still be linear. It turns out that a BINARY HEAP is an ideal structure for implementing a PQ. In particular, a binary heap can support logarithmic insert and remove in constant space. A binary heap is a binary tree with certain relational properties. ---------------------------------------------------------------------- 4. Binary Trees A -binary tree- is recursively defined as either - empty or - Node(info, lchild, rchild) where lchild and rchild are binary trees. Examples: t0 = empty t1 = Node(C, empty, empty) t2 = Node(L, empty, empty) t3 = Node(F, t1, t2) t4 = Node(Q, Node(N, empty, empty), empty) t5 = Node(N, empty, Node(Q, empty, empty)) are all binary trees. Subtrees: If t = Node(info, lchild, rchild) is a binary tree, then lchild and rchild are said to be -subtrees- of t. Leaves: A binary tree of the form Node(info, empty, empty), that is, with empty subtrees, is said to be a -leaf-. Binary Tree Diagrams - An empty binary tree has an empty diagram, - A leaf Node(info, empty, empty) is diagrammed as info, - Non-leaf binary trees such as t3-t5 are diagrammed as follows: t3: t4: t5: F Q N / \ / \ C L N Q Note: When using diagrams of binary trees, it's common to conflate the info field and the node. Thus, we would refer to node F or (leaf) node C in t3 above. Interior Nodes Non-leaf nodes such as F above are called -interior nodes-. Interior nodes are -parents- of their subtrees. Thus, - in t3, F is the parent of C and L, - in t4, Q is the parent of N and - in t5, N is the parent of Q. Full Binary Tree A binary tree t is a -full binary tree- if every node in t has either 0 or 2 children. Example: t1, t2 and t3 are full binary trees but t4 and t5 are not. Root A non-empty binary tree t will have exactly one node with no parent. This node is called the -root- of t. Levels Let t be a binary tree with root A and let B be a node in t. (B is sometimes refered to as a descendant of A.) The -level- of B is the number of steps from A to B. Example: In t3, F is at level 0, and C and L are both at level 1. Note that there can be at most 2^k nodes with level k. E.g., in t3 there are 2^1 = 2 nodes with level 1. The term -level- is also used as a property of a binary tree. Thus, we may refer to nodes at level k of t. Depth Let t be a binary tree. Then the -depth(t)- is the maximum level of any node in t. Example: The tree Node(G, t3, empty) has depth 2. G / F / \ C L Note that for a binary tree t with N nodes: int(log_2 N) <= depth(t) <= N - 1 Perfect Binary Tree A binary tree t is a -perfect binary tree- if each level of t is full. Thus, a perfect binary tree - with N nodes has depth int(log_2 N), - of depth k, will have 2^(k + 1) - 1 nodes. Complete Binary Tree A binary tree t is a -complete binary tree- if each level of t is full with the possible exception of the greatest one k. If level k is not full, all leaves must be to the left. Example t1, t2, t3 and t4 are complete binary trees. t5 is not. Representing Complete Binary Trees Complete binary trees can be represented in sequential storage. For example, we can represent t3 as: 0 1 2 3 a F C L Letting left(i) = i * 2 right(i) = i * 2 + 1 parent(i) = int(i / 2) we have a[left(1)] = C and a[right(1)] = L. Let t6 be (See SW p. 317): T / \ P R / \ / \ N H O A / \ / E I G Then t6 can be represented sequentially as: 0 1 2 3 4 5 6 7 8 9 10 a T P R N H O A E I G ---------------------------------------------------------------------- 5. Binary Heaps A max (min) binary heap Node(info, lchild, rchild) is a complete binary tree with a total order >= on the set of values in the info fields, and 1. if lchild = Node(info', _, _) then info >= info' and if rchild = Node(info'', _, _) then info >= info'' and 2. lchild and rchild are both max (min) binary heaps. Swimming and Sinking Insertion into a binary heap can be accomplished by swimming: T A binary heap into which we will insert S. / \ P R / \ / \ N H O A / \ / E I G T Add S at the end. No longer a binary heap, / \ because H and S are out of order. S must swim up. P R / \ / \ N H O A / \ / + E I G S T Not a binary heap, S to keep swimming. / \ P R / + / \ N S O A / \ / \ E I G H T The binary heap property is restored / \ in log_2 N time and no additional space! S R / \ / \ N P O A / \ / \ E I G H The delMax() (remove) operation can be implemented by sinking: T A binary heap. / \ S R / \ / \ N P O A / \ / \ E I G H Remove T, replacing it with H: H T ==> No longer a binary heap. Last elt H moved / \ to root, then to sink to correct spot. S R / \ / \ N P O A / \ / \ E I G S Not a binary heap. H must keep sinking. / \ H R / \ / \ N P O A / \ / \ E I G S Binary heap is restored, in Log_2 N steps! / \ P R / \ / \ N H O A / \ / \ E I G ---------------------------------------------------------------------- 6. Mutation WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING Mutable implementations of data types can wreak havoc on ordered data structures. Consider the snippet: PQ pq = new PQ(); Point p = new PointC(.5, .5), q = new PointC(.5, .7); pq.insert(p); pq.insert(q); p.setX(.8); // ! pq is no longer a binary heap! I.e., it no longer // works!