priority

    xiaoxiao2025-09-20  542

    priority_queue 调用 STL里面的 make_heap(), pop_heap(), push_heap() 算法 实 现,也算是堆的另外一种形式。

    先写一个用 STL 里面堆算法实现的与真正的STL里面的 priority_queue 用法相 似的 priority_queue, 以加深对 priority_queue 的理解

    #include <iostream> #include <algorithm> #include <vector>  using namespace std;  class priority_queue {     private:         vector<int> data;     public:         void push( int t ){             data.push_back(t);             push_heap( data.begin(), data.end());         }         void pop(){             pop_heap( data.begin(), data.end() );             data.pop_back();         }         int top()    { return data.front(); }         int size()   { return data.size();  }         bool empty() { return data.empty(); } };  int main() {     priority_queue  test;     test.push( 3 );     test.push( 5 );     test.push( 2 );     test.push( 4 );     while( !test.empty() ){         cout << test.top() << endl;         test.pop(); }     return 0; }

    STL里面的 priority_queue 写法与此相似,只是增加了模板及相关的迭代器什么的。

    priority_queue 对于基本类型的使用方法相对简单。 他的模板声明带有三个参数,priority_queue<Type, Container, Functional> Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。 Container 必须是用数组实现的容器,比如 vector, deque 但不能用 list. STL里面默认用的是 vector. 比较方式默认用 operator< , 所以如果你把后面俩个 参数 缺省的话,优先队列就是大顶堆,队头元素最大。 看例子

    #include <iostream> #include <queue>  using namespace std;  int main(){     priority_queue<int> q;     forint i= 0; i< 10; ++i ) q.push( rand() );     while( !q.empty() ){         cout << q.top() << endl;         q.pop();     }     getchar();     return 0; }

    如果要用到小顶堆,则一般要把模板的三个参数都带进去。 STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆 例子:

    #include <iostream> #include <queue>  using namespace std;  int main(){     priority_queue<int, vector<int>, greater<int> > q;     forint i= 0; i< 10; ++i ) q.push( rand() );     while( !q.empty() ){         cout << q.top() << endl;         q.pop();     }     getchar();     return 0; }

    对于自定义类型,则必须自己重载 operator< 或者自己写仿函数 先看看例子:

    #include <iostream> #include <queue>  using namespace std;  struct Node{     int x, y;     Node( int a= 0, int b= 0 ):         x(a), y(b) {} };  bool operator<( Node a, Node b ){     if( a.x== b.x ) return a.y> b.y;     return a.x> b.x; }

    这个函数写在Node结构体内作为一个友员函数也可以!  int main(){     priority_queue<Node> q;     forint i= 0; i< 10; ++i )     q.push( Node( rand(), rand() ) );     while( !q.empty() ){         cout << q.top().x << ' ' << q.top().y << endl;         q.pop();     }     getchar();     return 0; }

    自定义类型重载 operator< 后,声明对象时就可以只带一个模板参数。 但此时不能像基本类型这样声明 priority_queue<Node, vector<Node>, greater<Node> >; 原因是 greater<Node> 没有定义,如果想用这种方法定义 则可以按如下方式

    例子:

    #include <iostream> #include <queue>  using namespace std;  struct Node{     int x, y;     Node( int a= 0, int b= 0 ):         x(a), y(b) {} };  struct cmp{     bool operator() ( Node a, Node b ){         if( a.x== b.x ) return a.y> b.y;         return a.x> b.x; } };  int main(){     priority_queue<Node, vector<Node>, cmp> q;     forint i= 0; i< 10; ++i )     q.push( Node( rand(), rand() ) );     while( !q.empty() ){         cout << q.top().x << ' ' << q.top().y << endl;         q.pop();     }     getchar();     return 0; }

    以上例子的

    struct cmp{     bool operator() ( Node a, Node b ){         if( a.x== b.x ) return a.y> b.y;         return a.x> b.x; } };

    为重点。

    2

    #include <iostream> #include <functional> #include <cstdlib> #include <algorithm> #include <queue> #include <set> #include <vector> #include <string> using namespace std; struct Node{     int data;     Node(){}     Node(int n){data=n;} }; struct myCmp : binary_function<Node,Node,bool>{     bool operator () (const Node& a,const Node& b)     {         return a.data < b.data;     } }; /* 根据实践即便不从 binary_function 派生也是可以使用的 class myCmp{ public:     bool operator () (const Node& a,const Node& b)     {         return a.data < b.data;     } }; */ int main() {     priority_queue<Node,vector<Node>,myCmp> PQ;     Node arr[6]={1,-1,2,-2,3,-3};     sort(arr,arr+6,myCmp()); }

    这种自定义的仿函数的方式是比较通用的做法。

    如果容器中的元素类型是系统内置类型比如CString,那么我们自己写的比较函数一般不会被调用,因为系统实现的CString

    的时候已经实现了< > == != 等操作符的重载。这时我们可以写一个仿函数即可实现自定义的比较规则。比如如下代码:

    struct cmp {     bool operator () (const CString& lhs, const CString& rhs)     {         return lhs.CompareNoCase(rhs) > 0;     } };

    void PriorityQueueTest() {     std::priority_queue<  CString,   vector<CString>,   cmp  > Q;     CString node;     node = _T("5");     Q.push(node);     node = _T("6");     Q.push(node);     node = _T("4");     Q.push(node);     while (!Q.empty())     {         node = Q.top();         Q.pop();     } }

    可实现对CString从大到小的排序,即top的时候总是取得最小的元素。

    总结:

    1. 对自定义类型,我们可以重载<或者>操作符,也可以自定义仿函数

    2. 对系统内置类型,我们可以用仿函数来实现自定义排序规则

    3. 对于重载<操作符,我们可以只写第一个参数即可,对于重载>操作符,我们必须把三个参数都写全

    4. 重载操作符既可写成全局函数,也可以写成自定义类型的友员函数。

    参考资料:

    http://blog.163.com/zjut_nizhenyang/blog/static/1695700292010101632059540/

    http://www.cnblogs.com/mfryf/archive/2012/09/05/2671883.html

    http://www.cnblogs.com/flyoung2008/articles/2136485.html

    转载请注明原文地址: https://ju.6miu.com/read-1302849.html
    最新回复(0)