* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download Lecture 12: Heaps, Priority Queues, Heapsort, Greedy Algorithms
Survey
Document related concepts
Transcript
CS503: Twelfth Lecture, Fall 2008 UML and Heaps Michael Barnathan Here’s what we’ll be learning: • Review of Lab 2. • Software Engineering: – UML Diagrams. • Data Structures: – Heaps. – Priority Queues (revisited). • Algorithms: – Heapsort. • Theory: – “Greedy” algorithms. Blackjack Architecture UML • This is called a Unified Modeling Language (UML) Diagram. • I generated it in a program called ArgoUML. • It is a useful tool for developing software architectures for complex systems. – The assignments are getting more complex. – You may want to start considering some sort of structured modeling tool, such as UML. • You can automatically generate “stubs” from the UML, too. These include: – All classes defined in the UML file. – All properties defined in those classes. – Method headers defined in the UML. • All you need to do then is fill in the body of the methods. Symbols • There are four important relationships between classes in a UML diagram: – Inheritance (“IS-A”): – Association (“Uses”): – Aggregation (“HAS-A”): – Composition (“HAS-A and owns”): • The symbol is always on the base class. Inheritance in UML • This models the “extends” keyword in Java. • One class should inherit from another if it “is” a special type of the other. • For example, the Dealer is a Player. He’s playing in the game and has all of the choices a Player has. – Except that he uses an algorithm to decide his move, which is why takeTurn() was overridden. • Just having common functionality doesn’t mean something should inherit. – E.g. “Truck” and “FrenchHorn” can both honk, but a Truck is not a FrenchHorn, or vice versa. – Use interfaces to model this instead. Associations in UML • This models cases where one object needs another object to do something, but doesn’t actually own it. • For example, a Player requires a Deck to hit(). The card is being drawn from that Deck. • This is usually modeled by passing a Deck as an argument to the hit() function. • The method needs something to operate, so the caller supplies it. Aggregations in UML • This is when one class has instances of another, but doesn’t manage them. – That is, it isn’t responsible for creating or destroying those objects. • For example, Player have a hand of Cards, represented using a LinkedList. • The Player doesn’t create or destroy those cards, however; it simply retrieves them from the Deck. • This is represented with an array or other collection of objects as a member variable. – Not local arrays. If you only need the objects within one function, it’s an association, not an aggregation. Compositions in UML • Like aggregations, but compositions manage their objects. – Creating, destroying, or otherwise maintaining. • For example, a Deck is a composition of Cards. – When the Deck class is created, it creates 52 Card objects and places them in an array. – If the Deck were destroyed, the Cards would become inaccessible (except for the ones already in players’ hands). Examples A game of Blackjack has Players. Dealer inherits from Player. Players use a Deck when they hit. And a Deck. Decks have Cards. Multiplicities • The numbers on the ends of the arrows. • These answer the question “how many?” • Four common responses: – – – – “One A uses one B”: “One A uses many Bs”: “Many As use one B”: “Many As use many Bs”: 1..1 ____________ 1..1 1..1 ____________ 0..* 0..* ____________ 1..1 0..* ____________ 0..* • Read them from the arrow to the end. • Don’t worry about these as much as the general class model you construct. Blackjack Code • Here’s the code corresponding to the diagram I just showed. • Let’s get it on a terminal… • Questions? Do you understand what this code is doing? – If you’re struggling with the labs, it’s imperative that you figure out how the code is broken down and what it is doing. Heaps • Heaps are a special type of tree structure. – Because they’re complete trees, it actually makes sense to implement them using arrays. We’ll use trees for intuition. • There are two types: min-heaps and max-heaps. “Heap” usually refers to a max-heap. • These have the very nice property of storing the maximum value in the heap in the root node. (Or for a min-heap, the minimum). – This is called the heap property. • The root can be accessed immediately, which means you can find the maximum value in constant time. • And since these are recursive, you can find the maximum of each child heap in O(1) as well… Example 9 4 2 9 > 4 and 5 4 > 2 and 1 5 1 CRUD: Heaps. • • • • Insertion: Access: Updating an element: Deleting an element: ? O(log n). ? ? • • Search: Traversal: O(n). O(n). • Finding the maximum: O(1). • • • • Access and traversal are identical to trees. This does not partition the dataset anymore, so we can’t perform binary search. The constant-time max. is the primary reason these are useful structures. As always, enforcing the heap property requires extra work on insertion. Heap Insertion 1. Insert into the next empty space in the tree, from left to right. 8 4 2 9 5 1 3 Uh oh! This can violate the heap property. 2 Heap Insertion 2. If the heap property is violated, swap with the parent (or upheap) until it is valid. 8 4 2 9 5 1 3 2 Heap Insertion 2. If the heap property is violated, swap with the parent (or upheap) until it is valid. 8 4 9 2 5 1 3 2 Heap Insertion 2. If the heap property is violated, swap with the parent (or upheap) until it is valid. 8 9 4 2 5 1 3 2 Heap Insertion 2. If the heap property is violated, swap with the parent (or upheap) until it is valid. Now it’s valid! 9 8 4 2 5 1 3 2 Analysis of Insertion • If we keep track of the last node, we can find where to insert in constant-time. • And if we use an array, we can go from child to parent in constant-time. • So each swap is O(1). • This means the upheap operation is going to dominate. • At worst, we’ll have to swap up to the root. • This means a number of swaps proportional to the height of the tree. – Heaps are naturally balanced trees. • So what is the complexity of insertion? Updating 1. Find the value to update. 2. If the new value is greater than or equal to the old one, no further action is necessary. 3. If it is smaller, upheap to restore the heap property, as in insertion. Heap Deletion Note: Deletion may only take place at the root. 1. Replace the root with the last leaf’s value. 8 4 2 5 1 3 2 Heap Deletion Note: Deletion may only take place at the root. 1. Replace the root with the last leaf’s value. Heap property violated! 2 4 2 5 1 3 Heap Deletion 2. Downheap: Swap down from the root to the larger child until both children are less than the node being swapped or we hit a leaf. 2 4 2 5 1 3 Heap Deletion 2. Downheap: Swap down from the root to the larger child until both children are less than the node being swapped or we hit a leaf. 5 4 2 2 1 3 Heap Deletion 2. Downheap: Swap down from the root to the larger child until both children are less than the node being swapped or we hit a leaf. 5 4 2 3 1 2 Heap property restored! Deletion Analysis • • • • • The swaps are O(1). Finding the last node can be O(1). The downheap again dominates. We can perform up to height swaps. What, therefore, is the complexity? CRUD: Heaps. • • • • Insertion: Access: Updating an element: Deleting an element: O(log n). O(log n). O(log n). O(log n). • Search: • Traversal: O(n). O(n). • Finding the maximum: O(1). • • • • Another tree-based compromise structure. But no need to balance. Very useful when you need to find a minimum or maximum quickly. Where else did we use a maximum to define the order? Priority Queues Using Heaps • Recall that we implemented priority queues by sorting by priority either on the enqueue or dequeue operations. • The idea: Use the priority as the key of the heap and simply bundle the actual data along with the node. – The node with maximum priority is always going to be at the root. CRUD: Priority Queues • Enqueue (heaps): O(log n). • Dequeue (heaps): O(log n). • Peek at the top element: O(1). • Deletion from a heap takes O(log n) time, but peeking without deleting is O(1)! • This is a much better choice than the previous strategies we discussed. Heapsort • Very simple sorting algorithm based on heaps: – Insert every element into a heap. – Retrieve and delete the root until the heap is empty. • The resulting data is sorted. – A min-heap returns the data in ascending order. – A max-heap in descending order. • Not a stable sort, and one of the most difficult to devise a stable variation to. • n elements, log(n) time for each -> O(n log n). • This algorithm competes with quicksort and mergesort due to the O(n log n) worst-case guarantee and requirement of only constant space. • It’s also an extremely simple sort to implement if you have a heap data structure. Greedy Algorithms • Why does upheaping work? – Because the maximum at each level of the tree is guaranteed to be greater than anything below it. – Not just on the immediate level below it, but every level below it. • Finding the maximum is a good example of a “greedy” algorithm: one that makes the best possible short-term choice at each step. – For certain problems, this results in the best solution; e.g. the maximum of the whole heap at the root. Another Example • There are pennies, nickels, dimes, and quarters. How would you make change of an arbitrary amount of money using the smallest number of coins? – Let’s say we want to make change of $0.81… Never Reconsider • Greedy algorithms don’t reconsider their choices. They make them and move on. • You made change with quarters. • With what was left over, you went to dimes. • Then to nickels. • Then pennies. • You didn’t go back to quarters after checking the dimes. There was no need. Is one grain of sand a heap? • We discussed heaps this time. Next time, we’ll get into hashing, one of the most useful topics we’ll discuss in the entire course. • The lesson: – It’s sometimes best not to reconsider your choices, but to make them and move on.