The Priority Queue Abstract Data Type

advertisement
Priority Queues
- Ed. 2. and 3.: Chapter 7 –
- Ed. 4.: Chapter 8 -
Priority Queues
(Chapter 7)
• Priority Queue ADT
- Keys, Priorities, and Total order Relations
- Sorting with a Priority Queue
• Priority Queue implementation
- Implementation with an unsorted sequence
- Implementation with a sorted sequence
The Priority Queue Abstract Data
Type
Suppose that you have a few assignments from different
courses. Which assignment will you want to work on first?
Course
Database Systems
UNIX
Data Structure & Algorithm
Structured Systems Analysis
Priority
2
4
1
3
Due day
October 3
October 10
September 29
October 7
You set your priority based on due days. Due days are called
keys.
When you want to determine the priority for your assignments,
you need a value for each assignment, that you can compare
with each other.
key: An object that is assigned to an element as a specific
attribute for that element, which can be used to identify, rank,
or weight that element.
Example: Student records
Student Name
Bill Scott
Bob Jones
Alan Smith
Susan Kane
Student Number
110102
110140
110243
110176
Final Score
65
76
86
80
Any of the attributes, Student Name, Student Number, or Final
Score can be used as keys.
Note: Keys may not be unique (Final Score).
Example:
Brand
Motormaster
Goodyear
Michelin
Price
$61.49
$98.99
$101.99
Warranty (km)
110,000
220,000
150,000
Suppose we are looking for tires for a passenger car. How can
we weight the tires so we can select the tires?
The key may consist of not only one attribute such as price. In
fact, we want to consider factors such as brands and warranty
as well.
So the key may be more complex than just one value.
We want a comparison rule that will never contradict itself.
This requires that the rule define a total order relation.
total order relation:
•Reflexive property: k  k.
•Antisymmetric property: if k1  k2 and k2  k1 , then k1 = k2.
•Transitive property: if k1  k2 and k2  k3 , then k1  k3.
Examples:
Integers, real numbers, lexicographic order of character sequence.
Not everything can have a total order relation.
Non-example:
For 2-D vectors v1 = (x1, x2) and v2 = (x3, x4), define the
following ordering rule:
v1  v2 if x2 - x1 = = x4 - x3
Then we have
4-1=7-4
Therefore, (1, 4)  (4, 7) and (4, 7)  (1, 4).
But (1,4)  (7, 4), namely, the relation does not satisfy the
antisymmetric property.
If a comparison rule defines a total order relation, it will never
lead to a comparison contradiction.
the smallest key: If we have a finite number of elements with
a total order relation, then the smallest key, denoted by kmin, is
well-defined: kmin is the key that satisfies kmin  k for any other
key k.
Being able to find the smallest key is very important because in
many cases, we want to have the element with the smallest key.
priority queue: A container of elements, each having an
associated key that is provided at the time the element is
inserted.
The two fundamental methods of a priority queue P:
insertItem(k,e): Insert an element e with key k into P.
removeMin(): Return and remove from P an element with
the smallest key.
Example 7.1
The airline company keeps a priority queue of standby
passengers waiting to get a seat.
passenger 1
passenger 2
passenger 3
passenger 4
Fare Paid Frequent-Flyer
Status (0 - 6 stars)
$216
2
$198
6
$315
4
$267
5
Days of
Standby
15
20
7
10
The keys consist of three attributes: Fare paid, frequent-flyer
status, and days of standby.
Sorting with a Priority Queue
Recall that a priority queue has the method removeMin() to
remove and return the element with the smallest key. This fact
makes priority queues useful for sorting.
Assume we have a sequence S of n elements
The application has two steps:
1.Put the elements of S into an initially empty priority queue
P by calling the method insertItem() n times.
2.Extract elements from P by calling the method
removeMin() n times, and put them back into S in order.
Algorithm PriorityQueueSort( S, P )
for each element in S
get an element from S and assign it to variable e
call P.insertItem( e, e )
while P is not empty
call P.removeMin() to get an element from P
insert the element to S
Note that the keys are the elements themselves.
Example:
We have a sequence S with 6 integers (elements). Also we have
an empty priority queue P.
S
4
P
0
7
8
2 1
After the first step, all the elements are now in the priority
queue, with themselves as keys.
S
P
0,0
1,1
2,2
4,4
7,7
8,8
The first three elements have been extracted from P and
inserted into S in order. The element with the smallest key in P
now is 4,4, which will be extracted next time.
S
0 1
2
4,4
7,7
P
8,8
After the second step: Now the elements are sorted in S.
S
0 1
P
2 4
7
8
Methods of a Priority Queue
The priority queue abstract data type supports the following
methos:
size(): Return the number of elements in P.
Input: None; Output: Integer
isEmpty(): Test whether P is empty.
Input: None; Output: Boolean
inserItem(k,e): Insert a new element e with key k into P.
Input: Objects k (key) and e (element); Output: None
minElement(): Return (but do not remove) an element of P with the
smallest key; an error condition occurs if the priority queue
is empty.
Input: None; Output: Object (element)
minKey(): Return a smallest key in P; an error condition occurs if the
priority queue is empty.
Input: None; Output: Object (key)
removeMin(): Remove from P and return an element with the smallest
key; an error condition occurs if the priority queue is
empty.
Input: None; Output: Object (element)
Example 7.2: The following table shows a series of operations
and their effects on an initially empty priority queue P.
Operation
insertItem(5,A)
insertItem(9,C)
insertItem(3,B)
insertItem(7,D)
minElement()
minKey()
removeMin()
size()
removeMin()
removeMin()
removeMin()
removeMin()
isEmpty()
Output
B
3
B
3
A
D
C
“error”
true
Priority Queue
{(5,A)}
{(5,A),(9,C)}
{(3,B),(5,A),(9,C)}
{(3,B),(5,A),(7,D),(9,C)}
{(3,B),(5,A),(7,D),(9,C)}
{(3,B),(5,A),(7,D),(9,C)}
{(5,A),(7,D),(9,C)}
{(5,A),(7,D),(9,C)}
{(7,D),(9,C)}
{(9,C)}
{}
{}
{}
Items in a Priority Queue
Recall that when we insert an element into a priority queue, we
need to assign a key to the element. Later, when we need to
extract the element from the priority queue, we need to suppy
the key. Therefore, items stored in the priority queue are pairs.
Here is a Java implementation of the pairs as class Item.
public class Item {
private Object key, elem;
protected Item( Object k, Object e ) {
key = k;
elem = e;
}
public Object key() { return key; }
public Object element() { return elem; }
public void setKey( Object k ) { key = k; }
public void setElement( Object e ) { elem = e; }
}
The Comparator Abstract Data
Type
Recall that the priority queue method removeMin() returns the
element with the smallest key. To find the element with the
smallest key, keys of elements in a priority queue have to be
compared. This can be handled by objects called comparators.
The comparator abstract data type supports the following
methods:
isLessThan(a,b) True if and only if a is less than b.
Input: Pair of objects; Output: Boolean
isLessThanOrEqualTo(a,b): True if and only if a is less than or equal to b.
Input: Pair of objects; Output: Boolean
isEqualTo(a,b): True if and only if a and b are equal.
Input: Pair of objects; Output: Boolean
isGreaterThan(a,b): True if and only if a is greater than b.
Input: Pair of objects; Output: Boolean
isGreaterThanOrEqualTo(a,b): True if and only if a is greater than or equal to b.
Input: Pair of objects; Output: Boolean
isComparable(a): True if and only if a can be compared.
Input: Object; Output: Boolean
Class Lexicographic
As an application of the comparator ADT, here is a Java class
Lexicographic for comparison of 2-D points.
public class Lexicographic implements Comparator {
int xa, ya, xb, yb;
// Assume objects are class Point2D objects
private void getXY( Object a, Object b ) {
if( a == null || b == null )
throw new InvalidElementException(
"Null Argument" );
try {
xa = (( Point2D )a ).getX();
ya = (( Point2D )a ).getY();
xb = (( Point2D )b ).getX();
yb = (( Point2D )b ).getY();
}
catch( ClassCastException e ) {
throw new InvalidElementException(
"Argument not a Point2D" );
}
}
public boolean isLessThan( Object a, Object b ) {
getXY( a, b );
if( xa == xb )
return( ya < yb );
else
return( xa < xb );
}
Examples:
Object a
(1, 3)
(7, 1)
(4, 5)
Object b
(1, 4)
(5, 2)
(5, 2 )
return value
true
false
true
public boolean isLessThanOrEqualTo( Object a, Object b ) {
getXY( a, b );
if( xa == xb )
return( ya <= yb );
else
return( xa <= xb );
}
Examples:
Object a
(2, 3)
(7, 1)
(4, 5)
Object b
(2, 3)
(5, 2)
(5, 2 )
return value
true
false
true
public boolean isEqualTo( Object a, Object b ) {
getXY( a, b );
return ( xa == xb ) && ( ya == yb );
}
Examples:
Object a
(2, 3)
(7, 1)
(4, 5)
Object b
(2, 3)
(5, 2)
(5, 2 )
return value
true
false
false
public boolean isComparable( Object a ) {
if( a == null )
return a;
else {
try { Point2D p = ( Point2D )a; }
catch( ClassCastException e ) { return false; }
return true;
}
}
The function returns false if object a is null or it is not a
Poin2D type.
Data Structure Exercises 14.1
Implementing a Priority Queue
with a Sequence
Suppose that we want to write a program that using a priority
queue to help us select tires. How can we implement a priority
queue?
Brand
Motormaster
Goodyear
Michelin
Price
$61.49
$98.99
$101.99
Warranty (km)
110,000
220,000
150,000
Recall that both a sequence and a priority queue are containers
of some elements. Therefore, we can use a sequence to
implement a priority queue. The elements in the sequence are
the pairs of keys and elements.
There are two ways to implement a priority queue with a
sequence:
1.Keys in the sequence are sorted.
2.Keys in the sequence are not sorted.
Implementation with an Unsorted Sequence
Let S be a sequence. A pair of key and element is denoted as
p=(k,e). With an unsorted sequence, we use the method
insertLast(p) of S to implement insertItem(k,e) of the priority
queue P.
To perform operations including minElement, minKey, and
removeMin, we have to inspect all the elements of the
sequence S to find the element with the smallest key.
Example:
Assume we have the elements stored in an unsorted sequence
show here.
To perform the removeMin() operation, we have to inspect all
elements to find the element (0,0) that has the smallest key.
P
1,1
4,4
0,0
2,2
7,7
8,8
Implementation with an Sorted Sequence
Let S be a sequence. A pair of key and element is denoted as
p=(k,e). With an sorted sequence, we can easily extract the
element with the smallest key with the combination of methods
remove() and first() of S.
However, to perform operation insertItem, we need to scan
through the sequence S to find the apropriate position to insert
the new element and key.
Example:
To insert the pair (6,6), we have to scan through the sequence
until we find the right place (between (4,4) and (7,7)).
P
0,0
1,1
2,2
4,4
7,7
6,6
8,8
Comparing the Two Implementations
Assume that the size of the sequence is n.
Method
Unsorted S
size, isEmpty
fast
insertItem
fast
minElement, minKey, removeMin O(n)
Sorted S
fast
O(n)
fast
Class SortedSequencePriorityQueue
public class SortedSequencePriorityQueue
implements PriorityQueue {
protected Sequence S = new NodeSequence();
protected Comparator comp;
protected Object key( Position pos ) {
return (( Item )pos.element()).key();
}
protected Object elem( Position pos ) {
return (( Item )pos.element()).element();
}
protected Object elem( Object kep ) {
return (( Item )kep ).element()
}
public SortedSequencePriorityQueue( Comparator c ) {
comp = c;
}
public int size() { return S.size(); }
public boolean isEmpty() { return S.isEmpty() }
public void insertItem( Object k, Object e )
throws InvalidKeyException {
if( !comp.isComparable( k ))
throws new InvalidKeyException(
"The key is not valid" );
else if( S.isEmpty())
S.insertFirst( new Item( k, e ));
else if( comp.isGreaterThan( k,key(S.last())))
S.insertAfter( S.last(), new Item( k, e ));
else {
Position curr = S.first();
while( comp.isGreaterThan( k, key( curr )))
curr = S.after( curr );
S.insertBefore( curr, new Item( k, e ));
}
}
curr
P
0,0
1,1
2,2
4,4
7,7
6,6
k = 6, e = 6
8,8
public Object removeMin()
throws PriorityQueueEmptyException {
if( S.isEmpty())
throw new PriorityQueueEmptyException(
"The priority queue is empty" );
else
return elem( S.remove( S.first()));
}
Selection Sort and Insertion Sort
Recall that we can use a priority queue to sort elements.
Depending on whether a sorted sequence is used to implement
the priority queue, we have two kinds of sort.
If the priority queue is implemented with an unsorted sequence,
it is called selection-sort.
The table here shows the performance of selection sort on
sequence (7, 4, 8, 2, 5, 3, 9).
Input
Phase 1
Phase 2
Sequence S
(7, 4, 8, 2, 5, 3, 9)
(4, 8, 2, 5, 3, 9)
(8, 2, 5, 3, 9)
…
()
(2)
(2, 3)
(2, 3, 4)
(2, 3, 4, 5)
(2, 3, 4, 5, 7)
(2, 3, 4, 5, 7, 8)
(2, 3, 4, 5, 7, 8, 9)
Priority Queue P
()
(7)
(7, 4)
…
(7, 4, 8, 2, 5, 3, 9)
(7, 4, 8, 5, 3, 9)
(7, 4, 8, 5, 9)
(7, 8, 5, 9)
(7, 8, 9)
(8, 9)
(9)
()
If the priority queue is implemented with a sorted sequence, the
sort is called insertion sort. The table here shows the
performance of insertion sort on the same sequence
S = (7, 4, 8, 2, 5, 3, 9).
Input
Phase 1
Phase 2
Sequence S
(7, 4, 8, 2, 5, 3, 9)
(4, 8, 2, 5, 3, 9)
(8, 2, 5, 3, 9)
(2, 5, 3, 9)
(5, 3, 9)
(3, 9)
(9)
()
(2)
(2, 3)
…
(2, 3, 4, 5, 7, 8, 9)
Priority Queue P
()
(7)
(4, 7)
(4, 7, 8)
(2, 4, 7, 8)
(2, 4, 5, 7, 8)
(2, 3, 4, 5, 7, 8)
(2, 3, 4, 5, 7, 8, 9)
(7, 4, 8, 5, 3, 9)
(7, 4, 8, 5, 9)
…
()
The table here is a comparison of running time for both kinds
of sort.
Selection Sort Insertion Sort
Phase 1
O(n)
O(n2)
O(n)
Phase 2
O(n2)
Overall
O(n2)
O(n2)
Recall that the runnint time for bobble sort is also
propotional to the size of the square of n, the size of the
sequence.
Data Structure Exercises 15.1
Implementing a Priority Queue
with a Sequence
Suppose that we want to write a program that using a priority
queue to help us select tires. How can we implement a priority
queue?
Brand
Motormaster
Goodyear
Michelin
Price
$61.49
$98.99
$101.99
Warranty (km)
110,000
220,000
150,000
Recall that both a sequence and a priority queue are containers
of some elements. Therefore, we can use a sequence to
implement a priority queue. The elements in the sequence are
the pairs of keys and elements.
There are two ways to implement a priority queue with a
sequence:
1. Keys in the sequence are sorted.
2. Keys in the sequence are not sorted.
Implementation with an Unsorted Sequence
Let S be a sequence. A pair of key and element is denoted as
p=(k,e). With an unsorted sequence, we use the method
insertLast(p) of S to implement insertItem(k,e) of the priority
queue P.
To perform operations including minElement, minKey, and
removeMin, we have to inspect all the elements of the
sequence S to find the element with the smallest key.
Example:
Assume we have the elements stored in an unsorted sequence
show here.
To perform the removeMin() operation, we have to inspect all
elements to find the element (0,0) that has the smallest key.
P
1,1
4,4
0,0
2,2
7,7
8,8
Implementation with an Sorted Sequence
Let S be a sequence. A pair of key and element is denoted as
p=(k,e). With an sorted sequence, we can easily extract the
element with the smallest key with the combination of methods
remove() and first() of S.
However, to perform operation insertItem, we need to scan
through the sequence S to find the apropriate position to insert
the new element and key.
Example:
To insert the pair (6,6), we have to scan through the sequence
until we find the right place (between (4,4) and (7,7)).
P
0,0
1,1
2,2
4,4
7,7
6,6
8,8
Comparing the Two Implementations
Assume that the size of the sequence is n.
Method
Unsorted S Sorted S
size, isEmpty
fast
fast
insertItem
fast
minElement, minKey, removeMin
fast
Class SortedSequencePriorityQueue
public class SortedSequencePriorityQueue
implements PriorityQueue {
protected Sequence S = new NodeSequence();
protected Comparator comp;
protected Object key( Position pos ) {
return (( Item )pos.element()).key();
}
protected Object elem( Position pos ) {
return (( Item )pos.element()).element();
}
protected Object elem( Object kep ) {
return (( Item )kep ).element()
}
public SortedSequencePriorityQueue( Comparator c ) {
comp = c;
}
public int size() { return S.size(); }
public boolean isEmpty() { return S.isEmpty() }
public void insertItem( Object k, Object e )
throws InvalidKeyException {
if( !comp.isComparable( k ))
throws new InvalidKeyException(
"The key is not valid" );
else if( S.isEmpty())
S.insertFirst( new Item( k, e ));
else if( comp.isGreaterThan( k,key(S.last())))
S.insertAfter( S.last(), new Item( k, e ));
else {
Position curr = S.first();
while( comp.isGreaterThan( k, key( curr )))
curr = S.after( curr );
S.insertBefore( curr, new Item( k, e ));
}
}
curr
P
0,0
1,1
2,2
4,4
7,7
6,6
k = 6, e = 6
8,8
public Object removeMin()
throws PriorityQueueEmptyException {
if( S.isEmpty())
throw new PriorityQueueEmptyException(
"The priority queue is empty" );
else
return elem( S.remove( S.first()));
}
Selection Sort and Insertion Sort
Recall that we can use a priority queue to sort elements.
Depending on whether a sorted sequence is used to implement
the priority queue, we have two kinds of sort.
If the priority queue is implemented with an unsorted sequence,
it is called selection-sort.
The table here shows the performance of selection sort on
sequence (7, 4, 8, 2, 5, 3, 9).
Input
Phase 1
Phase 2
Sequence S
(7, 4, 8, 2, 5, 3, 9)
(4, 8, 2, 5, 3, 9)
(8, 2, 5, 3, 9)
…
()
(2)
(2, 3)
(2, 3, 4)
(2, 3, 4, 5)
(2, 3, 4, 5, 7)
(2, 3, 4, 5, 7, 8)
(2, 3, 4, 5, 7, 8, 9)
Priority Queue P
()
(7)
(7, 4)
…
(7, 4, 8, 2, 5, 3, 9)
(7, 4, 8, 5, 3, 9)
(7, 4, 8, 5, 9)
(7, 8, 5, 9)
(7, 8, 9)
(8, 9)
(9)
()
If the priority queue is implemented with a sorted sequence, the
sort is called insertion sort. The table here shows the
performance of insertion sort on the same sequence
S = (7, 4, 8, 2, 5, 3, 9).
Input
Phase 1
Phase 2
Sequence S
(7, 4, 8, 2, 5, 3, 9)
(4, 8, 2, 5, 3, 9)
(8, 2, 5, 3, 9)
(2, 5, 3, 9)
(5, 3, 9)
(3, 9)
(9)
()
(2)
(2, 3)
…
(2, 3, 4, 5, 7, 8, 9)
Priority Queue P
()
(7)
(4, 7)
(4, 7, 8)
(2, 4, 7, 8)
(2, 4, 5, 7, 8)
(2, 3, 4, 5, 7, 8)
(2, 3, 4, 5, 7, 8, 9)
(7, 4, 8, 5, 3, 9)
(7, 4, 8, 5, 9)
…
()
The table here is a comparison of running time for both kinds
of sort.
Selection Sort Insertion Sort
Phase 1
Phase 2
Overall
Recall that the runnint time for bobble sort is also propotional
to the size of the square of n, the size of the sequence.
Data Structure Exercises 15.1
Download