priority_queue,首先它是一个queue,即只允许在低端加入元素,并从顶端取出元素,除此之外别无其他存取元素的途径(故priority_queue不提供遍历功能,也不提供迭代器);再次它具有priority,即queue中的元素具有一定的priority:其内的元素自动依照元素的权值排列,权值最高者(也就是数值最高),排在最前面。注:在queue并非是依照严格的权值递减的顺序排列,而是每次保持顶端(对头)元素为queue中权值最高的元素(其内部采用heap来实现(默认是max heap))。
下面是stl_queue.h中的priority_queue源码:
class priority_queue{ public: typedef typename Sequence::value_type value_type; typedef typename Sequence::size_type size_type; typedef typename Sequence::reference reference; typedef typename Sequence::const_reference const_reference; protected: Sequencec; // 底层容器 Compare comp; // 元素大小比较标准 public: priority_queue(): c() {} explicit priority_queue(constCompare& x) : c(), comp(x) {} // 以下用到的make_heap(), push_heap(),pop_heap()都是泛型算法 // 注意,任何一个构造函数都立刻于底层容器内产生一个implicitrepresentation heap。 #ifdef __STL_MEMBER_TEMPLATES template <class InputIterator> priority_queue(InputIteratorfirst, InputIterator last, const Compare& x) : c(first, last), comp(x) { make_heap(c.begin(),c.end(), comp); } template <class InputIterator> priority_queue(InputIteratorfirst, InputIterator last) : c(first, last) { make_heap(c.begin(),c.end(), comp); } #else /* __STL_MEMBER_TEMPLATES */ priority_queue(constvalue_type* first, const value_type* last, const Compare& x) :c(first, last), comp(x) { make_heap(c.begin(), c.end(), comp); } priority_queue(constvalue_type* first, const value_type* last) : c(first, last) { make_heap(c.begin(),c.end(), comp); } #endif /* __STL_MEMBER_TEMPLATES */ bool empty()const { return c.empty(); } size_type size()const { return c.size(); } const_reference top()const { return c.front(); } void push(constvalue_type& x) { __STL_TRY { // push_heap 是泛型算法,先利用底层容器的push_back()将新元素 // 推入末端,再重排heap c.push_back(x); push_heap(c.begin(), c.end(), comp);// push_heap 是泛型演算法 } __STL_UNWIND(c.clear()); } void pop(){ __STL_TRY { // pop_heap 是泛型演算法,從 heap 內取出一個元素。它並不是真正將元素 // 彈出,而是重排heap,然後再以底層容器的pop_back() 取得被彈出 // 的元素。見C++ Primerp.1195。 pop_heap(c.begin(), c.end(), comp); c.pop_back(); } __STL_UNWIND(c.clear()); } };
priority_queue的使用示例1:
#include <iostream> #include <queue> using namespace std; class myComparison { bool reverse; public: myComparison(const bool& revParam = false) { reverse = revParam; } bool operator()(const int& lhs, const int& rhs) const { if(reverse) return (lhs > rhs); else return (lhs < rhs); } }; int main() { int myInts[] = {10, 60, 50 ,20}; priority_queue<int> first; priority_queue<int> second(myInts, myInts+4); cout << "second size: " << second.size() << endl; cout << "second top: " << second.top() << endl; second.push(100); cout << "second top: " << second.top() << endl; priority_queue<int, vector<int>, greater<int> > third(myInts, myInts+4); cout << "third size: " << third.size() << endl; cout << "third top: " << third.top() << endl; third.push(100); cout << "third top: " << third.top() << endl; //using myComparison priority_queue<int, vector<int>, myComparison > fourth; typedef priority_queue<int, vector<int>, myComparison> myPq_type; myPq_type fifth(myComparison() ); myPq_type sixth(myInts, myInts+4, myComparison(true) ); cout << "sixth top: " << sixth.top() << endl; sixth.pop(); cout << "sixth top: " << sixth.top() << endl; return 0; }
priority_queue的使用范例2:
//优先级队列 priority_queue by MoreWindows( http://blog.csdn.net/MoreWindows ) // 支持 empty() size() top() push() pop() 与stack的操作函数全部一样 //by MoreWindows #include <queue> #include <list> #include <cstdio> using namespace std; int main() { //优先级队列默认是使用vector作容器。 priority_queue<int> a; priority_queue<int, list<int>> b; //可以这样声明,但无法使用 int i; //压入数据 for (i = 0; i < 10; i++) { a.push(i * 2 - 5); //b.push(i); //编译错误 } //优先级队列的大小 printf("%d\n", a.size()); //取优先级队列数据并将数据移出队列 while (!a.empty()) { printf("%d ", a.top()); a.pop(); } putchar('\n'); return 0; }
下面程序是针对结构体的,对数据的比较是通过对结构体重载operator()。
程序功能是模拟排队过程,每人有姓名和优先级,优先级相同则比较姓名,开始有5个人进入队列,然后队头2个人出队,再有3个人进入队列,最后所有人都依次出队,程序会输出离开队伍的顺序。
//by MoreWindows( http://blog.csdn.net/MoreWindows ) #include <queue> #include <cstring> #include <cstdio> using namespace std; //结构体 struct Node { char szName[20]; int priority; Node(int nri, char *pszName) { strcpy(szName, pszName); priority = nri; } }; //结构体的比较方法 改写operator() struct NodeCmp { bool operator()(const Node &na, const Node &nb) { if (na.priority != nb.priority) return na.priority <= nb.priority; else return strcmp(na.szName, nb.szName) > 0; } }; void PrintfNode(Node &na) { printf("%s %d\n", na.szName, na.priority); } int main() { //优先级队列默认是使用vector作容器,底层数据结构为堆。 priority_queue<Node, vector<Node>, NodeCmp> a; //有5个人进入队列 a.push(Node(5, "小谭")); a.push(Node(3, "小刘")); a.push(Node(1, "小涛")); a.push(Node(5, "小王")); //队头的2个人出队 PrintfNode(a.top()); a.pop(); PrintfNode(a.top()); a.pop(); printf("--------------------\n"); //再进入3个人 a.push(Node(2, "小白")); a.push(Node(2, "小强")); a.push(Node(3, "小新")); //所有人都依次出队 while (!a.empty()) { PrintfNode(a.top()); a.pop(); } return 0; }
将上面结构体Node改成类:
类code:
class Node { public: Node(int nri, char *pszName) { strcpy(szName, pszName); priority = nri; } char* GetName(); int GetPriority(); char* GetName() const; int GetPriority() const; private: char szName[20]; int priority; }; char* Node::GetName() { return szName; } int Node::GetPriority() { return priority; } char* Node::GetName() const { return (char*)szName; } int Node::GetPriority() const { return priority; } inline bool operator < (const Node &na, const Node &nb) { if (na.GetPriority() != nb.GetPriority()) return na.GetPriority() <= nb.GetPriority(); else return strcmp(na.GetName(), nb.GetName()) > 0; }
程序code:
#include <queue> #include <cstring> #include <cstdio> using namespace std; void PrintfNode(Node &na) { printf("%s %d\n", na.GetName(), na.GetPriority()); } int main() { //优先级队列默认是使用vector作容器,底层数据结构为堆。 priority_queue<Node> a; //有5个人进入队列 a.push(Node(5, "小谭")); a.push(Node(3, "小刘")); a.push(Node(1, "小涛")); a.push(Node(5, "小王")); //队头的2个人出队 PrintfNode(a.top()); a.pop(); PrintfNode(a.top()); a.pop(); printf("--------------------\n"); //再进入3个人 a.push(Node(2, "小白")); a.push(Node(2, "小强")); a.push(Node(3, "小新")); //所有人都依次出队 while (!a.empty()) { PrintfNode(a.top()); a.pop(); } return 0; }