当向一个优先队列priority_queue用push()压入一个对象时
那个对象根据一个比较函数或函数对象在队列中排序
priority_queue确定用top()查看顶部元素时
该元素将使具有最高优先级的一个元素
创造一个用来处理int型数据的priority_queue是个很平常的工作
//: C07:PriorityQueue1.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <queue>
using namespace std;
int main() {
priority_queue<int> pqi;
srand(time(0)); // Seed the random number generator
for(int i = 0; i < 100; i++)
pqi.push(rand() % 25);
while(!pqi.empty()) {
cout << pqi.top() << ' ';
pqi.pop();
}
getchar();
} ///:~
输出
24 24 24 23 23 23 23 23 23 22 22 22 22 21 21 21 21 21 21 20 20 19 19 18 18 18 18 18 17 17 17 17 16 16 16 16 16 15 15 15 15 15 14 14 14 14 14 14 13 13 13 13 13 13 13 13 12 12 12 11 11 11 11 11 10 10 10 9 9 9 8 8 7 7 7 6 6 6 5 5 5 5 4 4 4 4 3 2 2 2 2 1 1 1 1 1 0 0 0 0
程序向priority_queue压入100个数值介于0到24之间的随机数
在运行这个程序时
会看到它允许出现重复的值
而且最高值先出现
通过用户自己的函数或函数对象以改变其元素的排列顺序
给予较低值的数以最高的优先级
//: C07:PriorityQueue2.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Changing the priority.
#include <cstdlib>
#include <ctime>
#include <functional>
#include <iostream>
#include <queue>
using namespace std;
int main() {
priority_queue<int, vector<int>, greater<int> > pqi;
srand(time(0));
for(int i = 0; i < 100; i++)
pqi.push(rand() % 25);
while(!pqi.empty()) {
cout << pqi.top() << ' ';
pqi.pop();
}
getchar();
} ///:~
输出
0 1 1 1 2 2 2 3 3 3 4 4 5 5 5 6 6 6 6 6 6 6 7 7 7 7 8 8 8 9 9 9 10 10 10 10 10 10 10 11 11 11 11 11 11 11 11 11 12 12 12 12 12 12 13 13 13 14 14 14 14 15 15 15 15 15 16 16 16 16 17 17 17 17 17 18 18 18 18 18 18 18 19 19 19 20 20 20 20 20 21 21 21 21 22 22 22 24 24 24
每个对象都包含一个string
和一个主优先级及一个次优先级的值
//: C07:PriorityQueue3.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// A more complex use of priority_queue.
#include <iostream>
#include <queue>
#include <string>
using namespace std;
class ToDoItem {
char primary;
int secondary;
string item;
public:
ToDoItem(string td, char pri = 'A', int sec = 1)
: primary(pri), secondary(sec), item(td) {}
friend bool operator<(
const ToDoItem& x, const ToDoItem& y) {
if(x.primary > y.primary)
return true;
if(x.primary == y.primary)
if(x.secondary > y.secondary)
return true;
return false;
}
friend ostream&
operator<<(ostream& os, const ToDoItem& td) {
return os << td.primary << td.secondary
<< ": " << td.item;
}
};
int main() {
priority_queue<ToDoItem> toDoList;
toDoList.push(ToDoItem("Empty trash", 'C', 4));
toDoList.push(ToDoItem("Feed dog", 'A', 2));
toDoList.push(ToDoItem("Feed bird", 'B', 7));
toDoList.push(ToDoItem("Mow lawn", 'C', 3));
toDoList.push(ToDoItem("Water lawn", 'A', 1));
toDoList.push(ToDoItem("Feed cat", 'B', 1));
while(!toDoList.empty()) {
cout << toDoList.top() << endl;
toDoList.pop();
}
getchar();
} ///:~
输出
A1: Water lawn
A2: Feed dog
B1: Feed cat
B7: Feed bird
C3: Mow lawn
C4: Empty trash
由于是与less<>一同工作
所以ToDoItem的operator<必须是一个非成员函数
除此之外 每一件事情都是自动发生的
priority_queue使用的容器是protected的
并且有标识符 根据标准C++规格说明 该标识符被命名为c
所以可以继承一个新类
//: C07:PriorityQueue4.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Manipulating the underlying implementation.
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iterator>
#include <queue>
using namespace std;
class PQI : public priority_queue<int> {
public:
vector<int>& impl() { return c; }
};
int main() {
PQI pqi;
srand(time(0));
for(int i = 0; i < 100; i++)
pqi.push(rand() % 25);
copy(pqi.impl().begin(), pqi.impl().end(),
ostream_iterator<int>(cout, " "));
cout << endl;
while(!pqi.empty()) {
cout << pqi.top() << ' ';
pqi.pop();
}
getchar();
} ///:~
输出
24 24 22 23 23 18 18 21 21 21 22 14 13 14 13 15 19 20 18 11 14 20 21 12 11 5 12 13 12 11 11 9 13 9 15 11 18 8 12 5 5 14 14 18 15 19 19 7 9 8 9 0 1 2 3 4 5 4 8 3 8 1 11 0 8 1 2 7 8 5 14 2 8 7 10 1 3 6 10 1 4 3 1 7 13 12 1 5 8 2 7 7 19 16 0 4 5 3 6 6
24 24 23 23 22 22 21 21 21 21 20 20 19 19 19 19 18 18 18 18 18 16 15 15 15 14 14 14 14 14 14 13 13 13 13 13 12 12 12 12 12 11 11 11 11 11 11 10 10 9 9 9 9 8 8 8 8 8 8 8 8 7 7 7 7 7 7 6 6 6 5 5 5 5 5 5 5 4 4 4 4 3 3 3 3 3 2 2 2 2 1 1 1 1 1 1 1 0 0 0
当调用pop()时
得到的这个vector包含的元素并不是按降序排列
就是想要从优先队列得到的顺序
//: C07:PriorityQueue5.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Building your own priority queue.
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iterator>
#include <queue>
using namespace std;
template<class T, class Compare>
class PQV : public vector<T> {
Compare comp;
public:
PQV(Compare cmp = Compare()) : comp(cmp) {
make_heap(this->begin(),this->end(), comp);
}
const T& top() { return this->front(); }
void push(const T& x) {
this->push_back(x);
push_heap(this->begin(),this->end(), comp);
}
void pop() {
pop_heap(this->begin(),this->end(), comp);
this->pop_back();
}
};
int main() {
PQV< int, less<int> > pqi;
srand(time(0));
for(int i = 0; i < 100; i++)
pqi.push(rand() % 25);
copy(pqi.begin(), pqi.end(),
ostream_iterator<int>(cout, " "));
cout << endl;
while(!pqi.empty()) {
cout << pqi.top() << ' ';
pqi.pop();
}
getchar();
} ///:~
输出
24 24 24 23 24 22 22 23 21 23 24 20 20 21 20 23 17 19 18 17 21 21 22 19 18 10 19 15 19 13 12 10 22 4 16 13 15 11 10 10 10 14 17 17 21 8 12 14 15 13 15 4 7 0 8 1 9 5 5 5 3 7 9 3 9 1 9 1 4 2 3 8 0 3 14 6 6 3 5 4 1 4 6 6 3 5 12 10 14 5 0 2 4 4 5 6 14 8 0 5
24 24 24 24 24 23 23 23 23 22 22 22 22 21 21 21 21 21 20 20 20 19 19 19 19 18 18 17 17 17 17 16 15 15 15 15 14 14 14 14 14 13 13 13 12 12 12 11 10 10 10 10 10 10 9 9 9 9 8 8 8 8 7 7 6 6 6 6 6 5 5 5 5 5 5 5 5 4 4 4 4 4 4 4 3 3 3 3 3 3 2 2 1 1 1 1 0 0 0 0
在vector底层中的一个被称为堆 heap的存储区
这个堆数据结构表现为一个优先队列的树的结构
在对其从头到尾进行迭代的时候
并不会得到一个线性的优先队列顺序
//: C07:PriorityQueue6.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iterator>
#include <queue>
using namespace std;
template<class T, class Compare>
class PQV : public vector<T> {
Compare comp;
bool sorted;
void assureHeap() {
if(sorted) {
// Turn it back into a heap:
make_heap(this->begin(),this->end(), comp);
sorted = false;
}
}
public:
PQV(Compare cmp = Compare()) : comp(cmp) {
make_heap(this->begin(),this->end(), comp);
sorted = false;
}
const T& top() {
assureHeap();
return this->front();
}
void push(const T& x) {
assureHeap();
this->push_back(x); // Put it at the end
// Re-adjust the heap:
push_heap(this->begin(),this->end(), comp);
}
void pop() {
assureHeap();
// Move the top element to the last position:
pop_heap(this->begin(),this->end(), comp);
this->pop_back();// Remove that element
}
void sort() {
if(!sorted) {
sort_heap(this->begin(),this->end(), comp);
reverse(this->begin(),this->end());
sorted = true;
}
}
};
int main() {
PQV< int, less<int> > pqi;
srand(time(0));
for(int i = 0; i < 100; i++) {
pqi.push(rand() % 25);
copy(pqi.begin(), pqi.end(),
ostream_iterator<int>(cout, " "));
cout << "\n-----" << endl;
}
pqi.sort();
copy(pqi.begin(), pqi.end(),
ostream_iterator<int>(cout, " "));
cout << "\n-----" << endl;
while(!pqi.empty()) {
cout << pqi.top() << ' ';
pqi.pop();
}
getchar();
} ///:~
输出
23
-----
23 16
-----
23 16 19
-----
23 20 19 16
-----
23 20 19 16 18
-----
23 20 19 16 18 15
-----
23 20 21 16 18 15 19
-----
23 20 21 16 18 15 19 11
-----
23 20 21 16 18 15 19 11 13
-----
23 20 21 16 18 15 19 11 13 14
-----
23 20 21 16 18 15 19 11 13 14 3
-----
23 20 21 16 18 15 19 11 13 14 3 14
-----
23 20 21 16 18 15 19 11 13 14 3 14 10
-----
23 20 21 16 18 15 19 11 13 14 3 14 10 17
-----
23 20 21 16 18 15 19 11 13 14 3 14 10 17 18
-----
23 20 21 16 18 15 19 11 13 14 3 14 10 17 18 2
-----
23 20 21 16 18 15 19 11 13 14 3 14 10 17 18 2 3
-----
23 20 21 16 18 15 19 11 16 14 3 14 10 17 18 2 3 13
-----
23 20 21 16 18 15 19 11 16 14 3 14 10 17 18 2 3 13 1
-----
23 20 21 16 18 15 19 11 16 14 3 14 10 17 18 2 3 13 1 3
-----
23 20 21 16 18 15 19 11 16 14 3 14 10 17 18 2 3 13 1 3 11
-----
23 23 21 16 20 15 19 11 16 14 18 14 10 17 18 2 3 13 1 3 11 3
-----
23 23 21 16 20 15 19 11 16 14 18 14 10 17 18 2 3 13 1 3 11 3 17
-----
23 23 21 16 20 15 19 11 16 14 18 14 10 17 18 2 3 13 1 3 11 3 17 7
-----
23 23 21 16 20 17 19 11 16 14 18 15 10 17 18 2 3 13 1 3 11 3 17 7 14
-----
23 23 21 16 20 17 19 11 16 14 18 15 16 17 18 2 3 13 1 3 11 3 17 7 14 10
-----
23 23 21 16 20 17 19 11 16 14 18 15 16 17 18 2 3 13 1 3 11 3 17 7 14 10 10
-----
23 23 21 16 20 17 19 11 16 14 18 15 16 17 18 2 3 13 1 3 11 3 17 7 14 10 10 4
-----
23 23 21 16 20 17 19 11 16 14 18 15 16 17 18 2 3 13 1 3 11 3 17 7 14 10 10 4 3
-----
23 23 21 16 20 17 21 11 16 14 18 15 16 17 19 2 3 13 1 3 11 3 17 7 14 10 10 4 3 18
-----
23 23 21 16 20 17 21 11 16 14 18 15 16 17 19 2 3 13 1 3 11 3 17 7 14 10 10 4 3 18 19
-----
23 23 21 22 20 17 21 16 16 14 18 15 16 17 19 11 3 13 1 3 11 3 17 7 14 10 10 4 3 18 19 2
-----
23 23 21 22 20 17 21 16 16 14 18 15 16 17 19 11 3 13 1 3 11 3 17 7 14 10 10 4 3 18 19 2 10
-----
23 23 21 22 20 17 21 22 16 14 18 15 16 17 19 11 16 13 1 3 11 3 17 7 14 10 10 4 3 18 19 2 10 3
-----
23 23 21 22 20 17 21 22 16 14 18 15 16 17 19 11 21 13 1 3 11 3 17 7 14 10 10 4 3 18 19 2 10 3 16
-----
23 23 21 22 20 17 21 22 16 14 18 15 16 17 19 11 21 13 1 3 11 3 17 7 14 10 10 4 3 18 19 2 10 3 16 2
-----
23 23 21 22 20 17 21 22 16 14 18 15 16 17 19 11 21 13 1 3 11 3 17 7 14 10 10 4 3 18 19 2 10 3 16 2 9
-----
24 23 21 23 20 17 21 22 22 14 18 15 16 17 19 11 21 13 16 3 11 3 17 7 14 10 10 4 3 18 19 2 10 3 16 2 9 1
-----
24 23 21 23 20 17 21 22 22 14 18 15 16 17 19 11 21 13 22 3 11 3 17 7 14 10 10 4 3 18 19 2 10 3 16 2 9 1 16
-----
24 23 21 23 20 17 21 22 22 14 18 15 16 17 19 11 21 13 22 6 11 3 17 7 14 10 10 4 3 18 19 2 10 3 16 2 9 1 16 3
-----
24 23 21 23 20 17 21 22 22 14 18 15 16 17 19 11 21 13 22 6 11 3 17 7 14 10 10 4 3 18 19 2 10 3 16 2 9 1 16 3 6
-----
24 23 21 23 20 17 21 22 22 14 18 15 16 17 19 11 21 13 22 6 11 3 17 7 14 10 10 4 3 18 19 2 10 3 16 2 9 1 16 3 6 1
-----
24 23 21 23 20 17 21 22 22 14 18 15 16 17 19 11 21 13 22 6 11 3 17 7 14 10 10 4 3 18 19 2 10 3 16 2 9 1 16 3 6 1 2
-----
24 23 21 23 20 17 21 22 22 14 18 15 16 17 19 11 21 13 22 6 11 8 17 7 14 10 10 4 3 18 19 2 10 3 16 2 9 1 16 3 6 1 2 3
-----
24 23 21 23 20 17 21 22 22 14 18 15 16 17 19 11 21 13 22 6 11 12 17 7 14 10 10 4 3 18 19 2 10 3 16 2 9 1 16 3 6 1 2 3 8
太多了省略
如果sorted为真
vector就不是作为一个堆来进行组织的
而仅仅是个排过序的序列
函数assureHeap()保证在对其进行任何堆操作之前使其倒退成为一个堆的形式
创建一个非vector的优先队列
每当需要时就构建一个使用vector的优先队列
//: C07:PriorityQueue7.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// A priority queue that will hand you a vector.
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iterator>
#include <queue>
#include <vector>
using namespace std;
template<class T, class Compare> class PQV {
vector<T> v;
Compare comp;
public:
// Don't need to call make_heap(); it's empty:
PQV(Compare cmp = Compare()) : comp(cmp) {}
void push(const T& x) {
v.push_back(x); // Put it at the end
// Re-adjust the heap:
push_heap(v.begin(), v.end(), comp);
}
void pop() {
// Move the top element to the last position:
pop_heap(v.begin(), v.end(), comp);
v.pop_back(); // Remove that element
}
const T& top() { return v.front(); }
bool empty() const { return v.empty(); }
int size() const { return v.size(); }
typedef vector<T> TVec;
TVec getVector() {
TVec r(v.begin(), v.end());
// It's already a heap
sort_heap(r.begin(), r.end(), comp);
// Put it into priority-queue order:
reverse(r.begin(), r.end());
return r;
}
};
int main() {
PQV<int, less<int> > pqi;
srand(time(0));
for(int i = 0; i < 100; i++)
pqi.push(rand() % 25);
const vector<int>& v = pqi.getVector();
copy(v.begin(), v.end(),
ostream_iterator<int>(cout, " "));
cout << "\n-----------" << endl;
while(!pqi.empty()) {
cout << pqi.top() << ' ';
pqi.pop();
}
getchar();
} ///:~
输出
24 24 24 24 23 23 23 23 23 23 23 22 21 21 21 20 20 19 19 18 18 18 18 18 18 16 16 16 16 15 15 15 14 14 14 14 13 13 13 13 13 13 13 13 12 12 12 12 11 11 10 10 10 10 10 10 10 9 8 8 8 8 8 7 7 7 7 7 7 7 7 6 6 6 6 5 5 5 5 4 4 3 3 3 3 2 2 2 2 2 1 1 1 1 0 0 0 0 0 0
-----------
24 24 24 24 23 23 23 23 23 23 23 22 21 21 21 20 20 19 19 18 18 18 18 18 18 16 16 16 16 15 15 15 14 14 14 14 13 13 13 13 13 13 13 13 12 12 12 12 11 11 10 10 10 10 10 10 10 9 8 8 8 8 8 7 7 7 7 7 7 7 7 6 6 6 6 5 5 5 5 4 4 3 3 3 3 2 2 2 2 2 1 1 1 1 0 0 0 0 0 0
PQV类模板随后采用了与STL的priority_queue相同的形式
但是拥有一个附加的成员函数getVector()
该函数创建一个从PQV中复制来的新的vector
//: C07:PriorityQueue8.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// A more compact version of PriorityQueue7.cpp.
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iterator>
#include <queue>
using namespace std;
template<class T> class PQV : public priority_queue<T> {
public:
typedef vector<T> TVec;
TVec getVector() {
TVec r(this->c.begin(),this->c.end());
// c is already a heap
sort_heap(r.begin(), r.end(), this->comp);
// Put it into priority-queue order:
reverse(r.begin(), r.end());
return r;
}
};
int main() {
PQV<int> pqi;
srand(time(0));
for(int i = 0; i < 100; i++)
pqi.push(rand() % 25);
const vector<int>& v = pqi.getVector();
copy(v.begin(), v.end(),
ostream_iterator<int>(cout, " "));
cout << "\n-----------" << endl;
while(!pqi.empty()) {
cout << pqi.top() << ' ';
pqi.pop();
}
getchar();
} ///:~
输出
24 24 24 23 23 23 23 23 22 22 22 22 21 21 21 20 19 19 19 19 18 18 18 17 17 17 17 17 17 16 16 16 15 15 15 15 14 14 14 14 14 14 14 14 13 13 13 13 12 12 12 12 12 11 11 10 10 9 9 9 9 9 9 9 8 8 7 6 6 5 5 5 5 5 5 4 4 4 4 4 4 3 3 3 3 3 2 2 2 2 2 2 1 1 1 1 1 1 0 0
-----------
24 24 24 23 23 23 23 23 22 22 22 22 21 21 21 20 19 19 19 19 18 18 18 17 17 17 17 17 17 16 16 16 15 15 15 15 14 14 14 14 14 14 14 14 13 13 13 13 12 12 12 12 12 11 11 10 10 9 9 9 9 9 9 9 8 8 7 6 6 5 5 5 5 5 5 4 4 4 4 4 4 3 3 3 3 3 2 2 2 2 2 2 1 1 1 1 1 1 0 0
保证用户不会得到一个处在未经排序状态的vector
使它变得简单且最令人期待
唯一潜在的问题就是成员函数getVector()采用传值的方式返回vector<T>