CS 261 – Data Structures Priority Queues & Heaps.
-
date post
20-Dec-2015 -
Category
Documents
-
view
222 -
download
1
Transcript of CS 261 – Data Structures Priority Queues & Heaps.
CS 261 – Data Structures
Priority Queues & Heaps
Priority 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:
public void add(Object val); public Object getFirst(); public void removeFirst();
•Examples of priority queues:–To do list with priorities–Active processes in an OS
Use 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.
Priority 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:1.Determine the times of each event using a random number generator with some distribution:
2.Put all events in a priority queue based on when it happens
3.Simulation framework pulls the minimum (next to happen) and executes the event
Priority 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 comparison based on the time
Priority Queues: Implementations
We can definitely do better than these!!!
SortedVector SortedList LinkedListadd O(n)
Binary searchSlide data up
O(n)Linear search
O(1)addLast(obj)
getFirst O(1)elementAt(0)
O(1)Returns head.obj
O(n)Linear search for smallest
valueremoveFirst O(n)
Slide data down
O(1) Reverse Order
O(n)head.remove()
O(n)Linear search then remove smallest
Priority Queues: Heaps•Heap: has 2 completely different meanings1.Classic data structure used to implement priority queues
2.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 node’s value is less than or equal to the values of its children
•Review: a complete binary tree is a tree in which1.Every node has at most two children (binary)
2.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
Heap: Example
2
5
8
3
79 10
14 12 11 16
Root = Smallest element
Next open spot
Last filled position(not necessarily the last object added)
Maintaining the Heap: Addition
2
5
8
3
79 10
14 12 11 16 4
Place new element in next available position,then fix it by “percolating up”
Add element: 4
New element innext open spot.
Maintaining the Heap: Addition (cont.)
Percolating up:while new value is less than parent,
swap value with parent
2
5
8
3
49 10
14 12 11 16 7
2
4
8
3
59 10
14 12 11 16 7
After first iteration (swapped with 7)
After second iteration (swapped with 5)New value not less than parent Done
Maintaining the Heap: Removal•Since each node’s 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):1.Replace root with the element in the last filled position
2.Fix heap by “percolating down”
Maintaining the Heap: Removal
2
5
8
3
79 10
14 12 11 16
Root = Smallest elementremoveFirst :1.Move value in lastelement into root
2. Percolate down
Last filled position
Maintaining the Heap: Removal (cont.)
Percolating down:while greater than smallest child
swap with smallest child
16
5
8
3
79 10
14 12 11
3
5
8
16
79 10
14 12 11
Root object removed(16 copied to root and last node removed)
After first iteration (swapped with 3)
Maintaining the Heap: Removal (cont.)
3
9
16
9
12
16
After second iteration (moved 9 up)
After third iteration (moved 12 up)Reached leaf node Stop percolatingPercolating down:
while greater than smallest childswap with smallest child
5
8710
14 12 11
8 3
5
8710
14 11
Maintaining the Heap: Removal (cont.)
3
5
8
9
712 10
14 16 11
Root = New smallest element
New last filled position
Heap 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
0
21
32
53
94
105
76
87
148
129
1110
16
2
5
8
3
79 10
14 12 11 16
2i + 1 and 2i + 2
floor((i - 1) / 2)
Heap Implementation: add (cont.)void addElement(DyArray da, EleType val) { int pos = dyArraySize(da); // Get index of next open spot. dyArrayAdd(da, val); // add element at end
int up = (pos – 1) / 2; // Get parent index (up the tree). ...
}
Example: add 4 to the heapPrior to addition, size = 11
0
21
32
53
94
105
76
87
148
129
1110
1611
4
Next open spot(pos)
Parent position(up)
A couple of Useful Routinesvoid swap (dyArray * da, int i, in j) {
// swap elements at I and j
EleType temp = dyArrayGet(da, i);
dyArrayPut(da, i, dyArrayGet(da, j));
dyArrayPut(da, j, temp);
}
int indexSmallest (dyArray * da, int i, int j) {
// return index of smallest element
if (LT(dyArrayGet(da, i), dyArrayGet(da, j)))
return i;
return j;
}
Heap Implementation: add (cont.) public void add(dyArray * da, EleType val) { ... // While not at root and new value is less than parent. while ((pos != 0) && (indexSmallest(da, pos, up) == pos)) { swap(da, pos, up); // swap values of parent and child pos = up; up = (pos - 1) / 2; // Move position and compute parent idx.
...
}
0
21
32
53
94
105
46
87
148
129
1110
1611
7
After first iteration: “swapped” new value (4) with parent (7)New parent value: 5
posup
Heap Implementation: add (cont.) public void add(dyArray * da, EleType val) { ... // While not at root and new value is less than parent. while ((pos != 0) && (indexSmallest(da, pos, up) == pos)) { swap(da, pos, up); // swap values of parent and child pos = up; up = (pos - 1) / 2; // Move position and compute parent idx.
...
}
0
21
32
43
94
105
56
87
148
129
1110
1611
7
After second iteration: “swapped” new value (4) with parent (5)New parent value: 2
posup
Heap Implementation: add (cont.) public void add(Dyarray * da, EleType val) { ... // While not at root and new value is less than parent. while ((pos != 0) && (indexSmallest(da, pos, up) == pos)) { . . . } // End while: reached root or parent is smaller than new value.
} // Done.
0
21
32
43
94
105
56
87
148
129
1110
1611
7
Second part of while test fails: stop iteration and add new value
posup
Heap Implementation: add (cont.)2
5
8
3
79 10
14 12 11 16 4
0
21
32
53
94
105
76
87
148
129
1110
1611
4
pos
up
Heap Implementation: add (cont.)
4
7
5
411
7
pos
up
2
5
8
3
9 10
14 12 11 16
0
21
32
53
94
106
87
148
129
1110
16
Heap Implementation: add (cont.)
4
5
2
45
5
posup
7
11
7
2
8
3
9 10
14 12 11 16
0
21
33
94
106
87
148
129
1110
16
Heap Implementation: add (cont.)
4
5
2
45
5
pos
7
11
7
2
8
3
9 10
14 12 11 16
0
21
33
94
106
87
148
129
1110
16
10
16
Heap Implementation: removeFirst void removeFirst(dyArray * da) { int last = dyArraySize(da) – 1; if (last != 0) // Copy the last element to
dyArrayPut(da,0, dyArrayGet(da, last)); // the first position.
dyArrayRemoveAt(da, last); // Remove last element. adjustHeap(dyArraySize(da), 0); // Rebuild heap property.}
0
21
32
43
94
105
56
87
148
129
11
Last element(last)
First element(elementAt(0))
1
32
43
94
105
56
87
148
129
110
7
11
7
10
1611
Heap Implementation: adjustHeapvoid adjustHeap(EleType * data, int max, int idx) {
val = 7
idx max
child (left child smallest)
min = 3
What’s next: val > min Copy min to parent spot (idx)Move idx to child
1
32
43
94
105
56
87
148
129
110
710
1611
Heap Implementation: adjustHeap (cont.)
2
4
8
3
59 10
14 12 11 16 7 last
1
32
43
94
105
56
87
148
129
110
211
710
16
Heap Implementation: adjustHeap (cont.)
7
4
8
3
59 10
14 12 11 16
1
32
43
94
105
56
87
148
129
110
71110
16
New root
max
Heap Implementation: adjustHeap (cont.)
7
4
8
3
59 10
14 12 11 16
1
32
43
94
105
56
87
148
129
110
710
16
Smallest child(min = 3)
val = 7
11
max
val > min Copy min to parent spot (idx)Move idx to child
Heap Implementation: adjustHeap (cont.)
3
4
8
7
59 10
14 12 11 16
1
72
43
94
105
56
87
148
129
110
310
16
val = 7
11
max
val > min Copy min to parent spot (idx)Move idx to child
idx
Heap Implementation: adjustHeap (cont.)
3
4
8
7
59 10
14 12 11 16
1
72
43
94
105
56
87
148
129
110
310
16
val = 7
11
max
If larger than both childrenDone
idx
Smallest child(min = 9)
AdjustHeap - Write recursivelyvoid adjustHeap (EleType * data, int max, int pos) {
int leftChild = pos * 2 + 1; int rightChild = pos * 2 + 2;
if (rightChild < max) { // have two children // get index of smallest // compare smallest child to pos // if necessary, swap and call adjustHeap(max, child)
} else if (leftChild < max) { // have only one child
// compare child to parent // if necessary, swap and call adjustHeap(max, child)
} // else no children, we are at bottom}
Priority Queues: Performance Evaluation
So, which is the best implementation of a priority queue?
SortedVector SortedList Heap
addElementO(n)
Binary searchSlide data up
O(n)Linear search
O(log n)Percolate up
getFirst O(1)elementAt(0)
O(1)Returns head.obj
O(1)Get root node
removeFirstO(n)
Slide data downO(1): Reverse
Order
O(1)head.remove()
O(log n)Percolate down
Priority Queues: Performance Evaluation•Remember that a priority queue’s 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)