Title: CS 261 Data Structures
1CS 261 Data Structures
2Priority Queues
- Not really a FIFO queue misnomer!!
- Associates a priority with each object
- First element has the highest priority
- A data structure that supports the PQueue
interface - void add(newvalue)
- Object getFirst()
- void removeFirst()
-
- Examples of priority queues
- To do list with priorities
- Active processes in an OS
3Use of Priority Queues in Simulations
- The original, and one of the most important uses
of Priority queues - Discrete Event Driven Simulation
- Actions are represented by events - things that
have (or will) happen at a given time - The PQ maintains list of pending events. Highest
priority is next event. - Event is pulled from list, executed, usually
spawns more events, which are then inserted into
the PQ. - Loop until everything happens, or until fixed
time is reached.
4Priority Queue Applications
- Discrete event-driven simulation i.e., a
simulation of a process where events occur - Example Ice cream store
- People arrive
- People order
- People leave
- Simulation Algorithm
- Determine the times of each event using a random
number generator with some distribution - Put all events in a priority queue based on when
it happens - Simulation framework pulls the minimum (next to
happen) and executes the event
5Priority Queue Applications
- Many types of events but they all have a time
when they occur - Can we store various types of events in a
priority queue? - Heterogeneous collection
- Keep a pointer to action, or a flag to tell what
action to perform - So, have your less than operator compare based on
the time
6Priority Queues Implementations
- We can definitely do better than these!!!
7Priority Queues Heaps
- Heap has 2 completely different meanings
- Classic data structure used to implement priority
queues - Memory space used for dynamic allocation
- We will study the data structure (not dynamic
memory allocation) - Heap data structure a complete binary tree in
which every nodes value is less than or equal to
the values of its children - Review a complete binary tree is a tree in which
- Every node has at most two children (binary)
- The tree is entirely filled except for the bottom
level which is filled from left to right
(complete) - Longest path is ceiling(log n) for n nodes
8Heap Example
Root Smallest element
2
5
3
8
7
9
10
14
12
11
16
Next open spot
Last filled position (not necessarily the last
object added)
9Maintaining the Heap Addition
2
Add element 4
5
3
8
7
9
10
New element in next open spot.
4
14
12
11
16
Place new element in next available
position, then fix it by percolating up
10Maintaining the Heap Addition (cont.)
2
5
3
2
8
4
9
10
4
3
14
12
11
16
7
After first iteration (swapped with 7)
8
5
9
10
14
12
11
16
7
After second iteration (swapped with 5) New
value not less than parent ? Done
Percolating up while new value is less than
parent, swap value with parent
11Maintaining the Heap Removal
- Since each nodes value is less than or equal to
the values of its children, the root is always
the smallest element - Thus, the PQueue methods getFirst and removeFirst
access and remove the root node, respectively - Heap removal (removeFirst)
- Replace root with the element in the last filled
position - Fix heap by percolating down
12Maintaining the Heap Removal
Root Smallest element
- removeFirst
- Move value in last
- element into root
- 2. Percolate down
2
5
3
8
7
9
10
14
12
11
16
Last filled position
13Maintaining the Heap Removal (cont.)
16
5
3
3
8
7
9
10
5
16
14
12
11
Root object removed (16 copied to root and last
node removed)
8
7
9
10
14
12
11
After first iteration (swapped with 3)
Percolating down while greater than smallest
child swap with smallest child
14Maintaining the Heap Removal (cont.)
3
9
5
3
16
8
7
10
8
9
5
14
12
11
After second iteration (moved 9 up)
12
8
7
10
16
14
11
After third iteration (moved 12 up) Reached leaf
node ? Stop percolating
Percolating down while greater than smallest
child swap with smallest child
15Maintaining the Heap Removal (cont.)
Root New smallest element
3
5
9
8
7
12
10
14
16
11
New last filled position
16Heap Representation
- Recall that a complete binary tree can be
efficiently represented by an array or a vector - Children of node at index i are stored at indices
- Parent of node at index i is at index
2i 1 and 2i 2
floor((i - 1) / 2)
2
5
3
8
7
9
10
14
12
11
16
0 2
1 3
2 5
3 9
4 10
5 7
6 8
7 14
8 12
9 11
10 16
17Heap Implementation add (cont.)
- void addElement(struct dyArray heap, EleType
val) - int pos dyArraySize(heap) // Get
index of next open spot. - dyArrayAdd(heap, val) // add
element at end - int up (pos 1) / 2 // Get parent
index (up the tree). - ...
-
- Example add 4 to the heap
- Prior to addition, size 11
Next open spot (pos)
Parent position (up)
0 2
1 3
2 5
3 9
4 10
5 7
6 8
7 14
8 12
9 11
10 16
11 4
18A word about Creating New Abstractions
- We could either
- Pass the container directly as a dynamic array,
or - Create a new structure for our heap, e.g.
- struct heap
- struct dyArray data
-
- One gives better leverage, but users have to
declare the dynamic array explicitly - Other is better encapsulation, but more work
19A couple of Useful Routines
- void swap (struct dyArray heap, int i, in j)
- / swap elements at I and j /
- EleType temp dyArrayGet(heap, i)
- dyArrayPut(heap, i, dyArrayGet(heap, j))
- dyArrayPut(heap, j, temp)
-
- int indexSmallest (struct dyArray heap, int i,
int j) - / return index of smallest element /
- if (LT(dyArrayGet(heap,i), dyArrayGet(heap,j))
lt 0) - return i
- return j
20Heap Implementation add (cont.)
- void addHeap(struct dyArray heap, EleType val)
- ...
- // While not at root and new value is less
than parent. - while ((pos ! 0) (indexSmallest(pos, up)
pos)) - swap(pos, up) // swap values of parent and
child - pos up up (pos - 1) / 2 // Move
position and compute parent idx. - ...
-
After first iteration swapped new value (4)
with parent (7) New parent value 5
pos
up
0 2
1 3
2 5
3 9
4 10
5 4
6 8
7 14
8 12
9 11
10 16
11 7
21Heap Implementation add (cont.)
- void addHeap(struct dyArray heap, EleType val)
- ...
- // While not at root and new value is less
than parent. - while ((pos ! 0) (indexSmallest(pos, up)
pos)) - swap(pos, up) // swap values of parent and
child - pos up up (pos - 1) / 2 // Move
position and compute parent idx. - ...
-
After second iteration swapped new value (4)
with parent (5) New parent value 2
pos
up
0 2
1 3
2 4
3 9
4 10
5 5
6 8
7 14
8 12
9 11
10 16
11 7
22Heap Implementation add (cont.)
- void addHeap(struct dyArray heap, EleType val)
- ...
- // While not at root and new value is less
than parent. - while ((pos ! 0) (indexSmallest(pos, up)
pos)) - . . .
- // End while reached root or parent is
smaller than new value. - // Done.
Second part of while test fails stop iteration
and add new value
pos
up
0 2
1 3
2 4
3 9
4 10
5 5
6 8
7 14
8 12
9 11
10 16
11 7
23Heap Implementation addHeap (cont.)
2
5
3
8
7
9
10
up
4
14
12
11
16
pos
0 2
1 3
2 5
3 9
4 10
5 7
6 8
7 14
8 12
9 11
10 16
11 4
24Heap Implementation addHeap (cont.)
2
5
3
up
4
8
9
10
pos
7
14
12
11
16
5 4
11 7
0 2
1 3
2 5
3 9
4 10
6 8
7 14
8 12
9 11
10 16
25Heap Implementation addHeap (cont.)
2
4
3
up
5
pos
8
9
10
7
14
12
11
16
2 4
5 5
11 7
0 2
1 3
3 9
4 10
6 8
7 14
8 12
9 11
10 16
26Heap Implementation addHeap (cont.)
2
4
3
5
pos
8
9
10
7
14
12
11
16
2 4
5 5
11 7
0 2
1 3
3 9
4 10
6 8
7 14
8 12
9 11
10 16
27Heap Implementation removeFirst
- void removeFirst(struct dyArray heap)
- int last dyArraySize(heap) 1
- if (last ! 0)
/ Copy the last element to / - dyArraySet(heap, 0, dyArrayGet(heap, last))
/ the first position. / - dyArrayRemoveAt(heap, last)
/ Remove last element. / - adjustHeap(heap, data.size(), 0)
/ Rebuild heap property./ -
Last element (last)
First element (elementAt(0))
10 16
0 2
1 3
2 4
3 9
4 10
5 5
6 8
7 14
8 12
9 11
11 7
1 3
2 4
3 9
4 10
5 5
6 8
7 14
8 12
9 11
0 7
10 16
11
28Heap Implementation adjustHeap
- void adjustHeap(struct dyArray heap, int max,
int idx) -
Whats next val gt min
? Copy min to parent spot (idx) Move idx to
child
child (left child smallest)
idx
max
min 3
1 3
2 4
3 9
4 10
5 5
6 8
7 14
8 12
9 11
0 7
10 16
11
val 7
29Heap Implementation adjustHeap (cont.)
2
4
3
8
5
9
10
7
14
12
11
16
last
1 3
2 4
3 9
4 10
5 5
6 8
7 14
8 12
9 11
0 2
11 7
10 16
30Heap Implementation adjustHeap (cont.)
7
4
3
8
5
9
10
New root
14
12
11
16
max
1 3
2 4
3 9
4 10
5 5
6 8
7 14
8 12
9 11
0 7
11
10 16
31Heap Implementation adjustHeap (cont.)
7
val gt min ? Copy min to parent spot (idx) Move
idx to child
4
3
val 7
8
5
9
10
Smallest child (min 3)
14
12
11
16
max
1 3
2 4
3 9
4 10
5 5
6 8
7 14
8 12
9 11
0 7
10 16
11
32Heap Implementation adjustHeap (cont.)
3
val gt min ? Copy min to parent spot (idx) Move
idx to child
4
7
val 7
8
5
9
10
idx
14
12
11
16
max
1 7
2 4
3 9
4 10
5 5
6 8
7 14
8 12
9 11
0 3
10 16
11
33Heap Implementation adjustHeap (cont.)
3
If larger than both children Done
4
7
val 7
8
5
9
10
idx
14
12
11
16
max
Smallest child (min 9)
1 7
2 4
3 9
4 10
5 5
6 8
7 14
8 12
9 11
0 3
10 16
11
34AdjustHeap - Write recursively
- void adjustHeap (struct dyArray heap, int max,
int pos) - int leftChild pos 2 1 int rightChild
pos 2 2 - if (rightChild lt max) // have two children
- // get index of smallest
- // compare smallest child to pos
- // if necessary, swap and call
adjustHeap(max, child) - else if (leftChild lt max) // have only one
child - // compare child to parent
- // if necessary, swap and call
adjustHeap(max, child) - // else no children, we are at bottom
35Priority Queues Performance Evaluation
- So, which is the best implementation of a
priority queue?
36Priority Queues Performance Evaluation
- Remember that a priority queues main purpose is
rapidly accessing and removing the smallest
element! - Consider a case where you will insert (and
ultimately remove) n elements - ReverseSortedVector and SortedList
- Insertions n n n2
- Removals n 1 n
- Total time n2 n O(n2)
- Heap
- Insertions n log n
- Removals n log n
- Total time n log n n log n 2n log n
O(n log n)