STL源码剖析 [容器](八)[priority_queue]

来源:互联网 发布:fsockopen php 开启 编辑:程序博客网 时间:2024/05/22 02:21

       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;elsereturn 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();elsereturn 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;}


 

 


0 0
原创粉丝点击