为了研究priority_queue,我们先写一段错误代码:
#include <iostream>
#include <queue>
using namespace std;
struct Node
{
int key;
int value;
};
int main()
{
Node nodes[2]={1,0,2,0};
priority_queue<> pqLess; //这里是故意的错误!
for(int i=0;i<sizeof(nodes)/sizeof(Node);++i)
pqLess.push(nodes[i]);
return 0;
}
编译结果:
--------------------Configuration: s - Win32 Debug--------------------
Compiling...
s.cpp
D:/downloads/CORC++/s.cpp(14) : error C2976: 'priority_queue' : too few template arguments
d:/program files/microsoft visual studio/vc98/include/queue(96) : see declaration of 'priority_queue'
D:/downloads/CORC++/s.cpp(14) : error C2079: 'pqLess' uses undefined class 'priority_queue<>'
D:/downloads/CORC++/s.cpp(16) : error C2228: left of '.push' must have class/struct/union type
执行 cl.exe 时出错.
s.exe - 1 error(s), 0 warning(s)
点击第一个错误,跟踪到头文件queue里面,发现了priority_queue类的声明如下(汉字部分注释为我后加上去的,如果有错误请指正):
// TEMPLATE CLASS priority_queue
template<class _Ty, class _C = vector<_Ty>, /*第一个class _Ty为priority_queue中成员的类型,第二个class _C为priority_queue的存储类型,并且已经默认为了vector<_Ty>存储,即vector的存储类型为_Ty,也就是存 储了我们要放在priority_queue中的数据类型,其中_Ty应该是type是缩写,_C是class的缩写,即第一个参数是一个类型,第二个参 数是一个类,用于存储数据*/
class _Pr = less<_C::value_type> > /*第三个class _Pr是一个比较方式类,且默认是_C中值的类型比较的less关系,其实一个函数指针就应该可以的,为什么要做成一个类呢?*/
class priority_queue {
public:
typedef _C::allocator_type allocator_type;
typedef _C::value_type value_type;
typedef _C::size_type size_type;
explicit priority_queue(const _Pr& _X = _Pr(), //explicit防止隐式转换
const allocator_type& _Al = allocator_type())
: c(_Al), comp(_X) {}
typedef const value_type *_It;
priority_queue(_It _F, _It _L, const _Pr& _X = _Pr(),
const allocator_type& _Al = allocator_type())
: c(_Al), comp(_X)
{for (; _F != _L; ++_F)
push(*_F); }
allocator_type get_allocator() const
{return (c.get_allocator()); }
bool empty() const
{return (c.empty()); }
size_type size() const
{return (c.size()); }
value_type& top()
{return (c.front()); }
const value_type& top() const
{return (c.front()); }
void push(const value_type& _X)
{c.push_back(_X);
push_heap(c.begin(), c.end(), comp); }
void pop()
{pop_heap(c.begin(), c.end(), comp);
c.pop_back(); }
protected:
_C c;
_Pr comp;
};
为了研究一下operator(),我们先故意写一段错误的代码:
#include <iostream>
#include <queue>
using namespace std;
struct Node
{
int key;
int value;
};
int main()
{
Node nodes[2]={1,0,2,0};
priority_queue<Node> pqLess; /*这句等价于priority_queue<Node,vector<Node>,less<Node> > pqLess; 根据上面的内容*/
for(int i=0;i<sizeof(nodes)/sizeof(Node);++i)
pqLess.push(nodes[i]);
return 0;
}
编译结果如下:
--------------------Configuration: s - Win32 Debug--------------------
Compiling...
s.cpp
d:/program files/microsoft visual studio/vc98/include/functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::vector<_Ty,_A> &,const class std::vector<_Ty,_A> &)' : could not deduce template argument for 'const class std::vector
<_Ty,_A> &' from 'const struct Node'
d:/program files/microsoft visual studio/vc98/include/functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct Node>::operator ()(const struct Node &,const struct Node &) const'
d:/program files/microsoft visual studio/vc98/include/functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::deque<_Ty,_A> &,const class std::deque<_Ty,_A> &)' : could not deduce template argument for 'const class std::deque<_T
y,_A> &' from 'const struct Node'
d:/program files/microsoft visual studio/vc98/include/functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct Node>::operator ()(const struct Node &,const struct Node &) const'
d:/program files/microsoft visual studio/vc98/include/functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::reverse_iterator<_RI,_Ty,_Rt,_Pt,_D> &,const class std::reverse_iterator<_RI,_Ty,_Rt,_Pt,_D> &)' : could not deduce te
mplate argument for 'const class std::reverse_iterator<_RI,_Ty,_Rt,_Pt,_D> &' from 'const struct Node'
d:/program files/microsoft visual studio/vc98/include/functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct Node>::operator ()(const struct Node &,const struct Node &) const'
d:/program files/microsoft visual studio/vc98/include/functional(86) : error C2784: 'bool __cdecl std::operator <(const struct std::pair<_T1,_T2> &,const struct std::pair<_T1,_T2> &)' : could not deduce template argument for 'const struct std::pair<
_T1,_T2> &' from 'const struct Node'
d:/program files/microsoft visual studio/vc98/include/functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct Node>::operator ()(const struct Node &,const struct Node &) const'
d:/program files/microsoft visual studio/vc98/include/functional(86) : error C2676: binary '<' : 'const struct Node' does not define this operator or a conversion to a type acceptable to the predefined operator
d:/program files/microsoft visual studio/vc98/include/functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct Node>::operator ()(const struct Node &,const struct Node &) const'
执行 cl.exe 时出错.
s.exe - 1 error(s), 0 warning(s)
点击错误,跟踪到了functional头文件中的less结构体,如下:
// TEMPLATE STRUCT less
template<class _Ty>
struct less : binary_function<_Ty, _Ty, bool> {
bool operator()(const _Ty& _X, const _Ty& _Y) const
{return (_X < _Y); } //这一行。
};
其原因是我们没有重载自定义数据类型Node的比较函数 <。
在代码中加上:
Bool operator <(const Node & a,const Node & b){return a.key<b.key;} 即可。
注意less结构体由binary_function“继承”而来,再查找functional头文件中的binary_function,其声明如下(汉字部分注释为我后加上去的,如果有错误请指正):
// TEMPLATE STRUCT binary_function
template<class _A1, class _A2, class _R>
struct binary_function { //二元操作符
typedef _A1 first_argument_type; //参数一
typedef _A2 second_argument_type; //参数二
typedef _R result_type; //返回类型
};
由此看出了priority_queue中的第三个模板只充当了一个函数指针的作用,priority_queue在对优先级排序的时候需要调用第三个类,并通过它知道哪些元素具有更高的“优先度”。用户也可以写自己的“比较类”,重载括号进行用户需要进行的比较。
常见的对自定义的复合数据类型使用STL需要比较的时候,有如下一些实现方式(目前只列得出两种):
1:重载大于小于号,然后用less和greater。
#include <iostream>
#include <queue>
using namespace std;
struct Node
{
int key;
int val;
};
bool operator >(const Node & a,const Node & b)
{
return a.key>b.key;
}
bool operator <(const Node & a,const Node & b)
{
return a.key<b.key;
}
int main()
{
Node nodes[2]={1,2,2,3};
priority_queue<Node,vector<Node>,less<Node> > pqLess;
priority_queue<Node,vector<Node>,greater<Node> > pqGreater;
for(int i=0;i<sizeof(nodes)/sizeof(Node);++i)
pqLess.push(nodes[i]),pqGreater.push(nodes[i]);
cout<<pqLess.top().key<<endl;
cout<<pqGreater.top().key<<endl;
return 0;
}
2:自定义一个比较“类”,重载括号,operator (),这这种方式可以由less“继承”。
#include <iostream>
#include <queue>
using namespace std;
struct Node
{
int key;
int value;
};
struct cmpLess
{
bool operator ()(const Node & a,const Node & b)
{
return a.key<b.key;
}
};
struct cmpGreater
{
bool operator ()(const Node & a,const Node & b)
{
return a.key>b.key;
}
};
int main()
{
Node nodes[2]={1,0,2,0};
priority_queue<Node,vector<Node>,cmpLess> pqLess;
priority_queue<Node,vector<Node>,cmpGreater> pqGreater;
for(int i=0;i<sizeof(nodes)/sizeof(Node);++i)
pqLess.push(nodes[i]),pqGreater.push(nodes[i]);
cout<<pqLess.top().key<<endl;
cout<<pqGreater.top().key<<endl;
return 0;
}
原文地址:http://yangmei.yan1988.blog.163.com/blog/static/25026753201010754613995/