priority_queue,以及运算符重载

来源:互联网 发布:ubuntu中文 命令 编辑:程序博客网 时间:2024/05/29 14:08

为了研究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/

0 0
原创粉丝点击