-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpriority.h
139 lines (111 loc) · 3.29 KB
/
priority.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// priority.h
//
// PriorityQueue: binary heap priority queue
//
// Copyright 2013 Systems Deployment, LLC
// Author: Morris Bernstein ([email protected])
#if !defined(CSS343_PRIORITY_H)
#define CSS343_PRIORITY_H
#include <cassert>
#include <cstdlib>
#include <vector>
// This priority queue implementation stores pointers to Things, using
// a Compare function object that returns a numeric value <0, =0, or
// >0 for <, ==, and >. It is assumed that the Thing class has
// methods int get_priority() and void set_priority(int). These hold
// indices into the priority queue to simplify implementation of the
// reduce (decrease_key) method.
template<typename Thing, typename Compare>
class PriorityQueue {
public:
PriorityQueue(Compare compare) : compare_(compare) {}
// Add a new thing to the priority queue.
void push_back(Thing* thing);
// Decrease (raise?) the priority of a given Thing.
void reduce(Thing* thing);
// Remove and return the lowest (highest?) priority Thing. This
// differs from std::priority_queue which has separate functions.
// Returns NULL if the queue is empty.
Thing* pop();
bool empty() { return data_.empty(); }
Thing* getElement(int index);
int getSize() { return data_.size(); }
private:
void swap(int n1, int n2);
void sift_up(int n);
void sift_down(int n);
Compare compare_;
std::vector<Thing*> data_;
};
template<typename Thing, typename Compare>
void PriorityQueue<Thing, Compare>::swap(int n1, int n2) {
Thing* tmp = data_[n1];
data_[n1] = data_[n2];
data_[n2] = tmp;
data_[n1]->set_priority(n1);
data_[n2]->set_priority(n2);
}
template<typename Thing, typename Compare>
void PriorityQueue<Thing, Compare>::sift_up(int n) {
if (n == 0) {
return;
}
int parent = (n + 1) / 2 - 1;
if (compare_(data_[parent], data_[n]) > 0) {
swap(parent, n);
sift_up(parent);
}
}
template<typename Thing, typename Compare>
void PriorityQueue<Thing, Compare>::sift_down(int n) {
unsigned left = (n + 1) * 2 - 1;
if (left >= data_.size()) {
return;
}
unsigned right = left + 1;
if (compare_(data_[n], data_[left]) >= 0) {
if (right >= data_.size() || compare_(data_[left], data_[right]) <= 0) {
swap(n, left);
sift_down(left);
}
else {
swap(n, right);
sift_down(right);
}
}
else if (right < data_.size() && compare_(data_[n], data_[right]) > 0) {
swap(n, right);
sift_down(right);
}
}
template<typename Thing, typename Compare>
void PriorityQueue<Thing, Compare>::push_back(Thing* thing) {
int n = data_.size();
thing->set_priority(n);
data_.push_back(thing);
sift_up(n);
}
template<typename Thing, typename Compare>
void PriorityQueue<Thing, Compare>::reduce(Thing* thing) {
int current_priority = thing->get_priority();
assert(data_[current_priority] == thing);
sift_up(current_priority);
}
template<typename Thing, typename Compare>
Thing* PriorityQueue<Thing, Compare>::pop() {
if (data_.size() == 0) {
return NULL;
}
Thing* min = data_[0];
data_[0] = *data_.rbegin();
data_[0]->set_priority(0);
data_.pop_back();
sift_down(0);
return min;
}
template<typename Thing, typename Compare>
inline Thing* PriorityQueue<Thing, Compare>::getElement(int index)
{
return data_[index];
}
#endif