Heaps and Greedy Algorithms
Download
Report
Transcript Heaps and Greedy Algorithms
CS305/503, Spring 2009
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.
Lab Questions?
• Any questions about the lab?
• Want to review the code itself?
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.
• 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.
No need to balance, but search time is now linear.
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.