关于stl优先队列重载小于运算符的问题
来源:互联网 发布:淘宝买ps4哪家店好 编辑:程序博客网 时间:2024/05/29 14:34
class G
{
public:
int step;
int p;
};
bool operator<(const G &a,const G &b)
{
if(a.step>b.step)
return true;
else
if(a.p>b.p)
return true;
else
return false;
}
主函数中使用优先队列
priority_queue<G> q;
这样的使用在vs2008下是会报错的。但貌似VC6下不会报错。
打断点跟了下,发现当a.step>b.step且b.p>a.p时就会报错。
也就是当输入为(a,b)时返回true,而输入为(b,a)时也返回true时就会报错~
在网上问了加上自己打断点跟到的说下这个优先队列
下面这段是csdn上qq120848369回答的
priority_queue一般就是用堆做的,记不清了,默认是用less比较实现的大根堆,比如当先维护堆,从父结点A开始下降整理堆,它会用A的孩子B与A调用less<>对象假设名字叫cmp,会这样传参,if(cmp(A,B)){那么调换A,B结点值} ,less里肯定是 return A<B; 所以我们想要实现小根堆,在传参次序为(A,B)的情况下,只能修改比较函数cmp,如果A<B,返回false,A>B才返回真。
qq120848369还给出了相关的代码:
class G
{
friend struct cmp;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private:
int step;
int p;
};
~~~~~~~~
struct cmp
{
bool operator()(const G&a,const G &b)
{
if(a.step > b.step)
return true;
else if(a.step < b.step)
return false;
else
return a.p>b.p;
}
};
int main()
{
priority_queue<G,vector<G>,cmp> q;
~~~~~~~~~~~~~~~~~~~~~~~~~~~
return 0;
}
(代码被我删掉很多,这里只是相关的部分。)
还有ddc回答的
c++标准里,返回个bool 的函数/仿函数叫Predicates,但是有规定,行为必须是确定的(大概是这个意思,_Pred(Left,Rigth) 和 !_Pred(Right,Left)相等,具体原话我记不得了).你那个不是Predicates,所以运行出错,VC6估计没做这个判断,但行为是不确定的。
~~~~~~~~~~~~
计算机理解的并不一定是你要表达的,在范型算法里,大量while(),像这种比较、交换等算法,如果a<b,swap(a,b),下一个循环到此如果b<a,swap(b,a),就会构成死循环。我只是举个例子,估计现在没这种问题,而且以后也不一定会碰到,但是写STL那些人想到了,所以在那里加了行_DEBUG_ERROR2.
话说回来,(5,2),(6,5),(5,1)都插入队列,你认为该是什么顺序呢?反过来在插一遍呢,是你要的结果吗?总有一个(5,2)和(5,1)顺序和你的预期不一样吧
~~~~~~~~~~~~
下面说下自己的
打断点跟到了xutility里头的这段报错的代码
template<class _Pr, class _Ty1, class _Ty2> inline
bool __CLRCALL_OR_CDECL _Debug_lt_pred(_Pr _Pred, _Ty1& _Left, _Ty2& _Right,
const wchar_t *_Where, unsigned int _Line)
{ // test if _Pred(_Left, _Right) and _Pred is strict weak ordering
if (!_Pred(_Left, _Right))
return (false);
else if (_Pred(_Right, _Left))
_DEBUG_ERROR2("invalid operator<", _Where, _Line);
return (true);
}
仔细看下发现这里头只对_Pred(_Left, _Right)返回true时做了_Pred是否等于!_Pred的判断,_Pred返回为false时没有做这个检查。不过返回个false对排序没有影响,返回为true时才做交换。于是和ddc说的一样,如果没有这样的判断很难保证当(a,b)==(b,a)==true时不会陷入死循环,a和b两个就一直交换下去。
不光是重载这个<运算符,在一些排序算法中这样的问题也是非常值得注意的。
同时打断点跟到的队列数据并非是有序的存储的,说明可能就是用的堆的方式来存储的。
在说下在c++ primer上看到的
栈和队列都是基于deque容器实现的,而优先队列则默认基于vector实现的。
同时可以覆盖其基础容器类型。
使用类似qq120848369给出的代码中的方式
priority_queue<G,vector<G>,cmp> q;
不过对使用的容器有一定的限制。
stack可以选用vector,list
queue需要容器提供push_front操作,所以只能选用list
priority_queue则需要提供随机访问的功能,因此只能建立在vector上。
这里附带一点关于vector的,vector使用的是一维数组的方式存储的。当存储的元素个数超出数组的大小时,vector将重新分配空间。
- 关于stl优先队列重载小于运算符的问题
- C++ STL 重载运算符小于号的巧妙
- C++ STL 重载运算符小于号的巧妙
- C++STL系列 结构体运算符重载及优先队列的使用
- 优先队列运算符重载
- 优先队列——重载运算符
- 优先队列中重载运算符>和<
- 优先队列 重载运算符详解
- STL运算符重载问题
- 优先队列之重载运算
- 关于运算符重载的问题
- 优先队列的结构体排序-重载运算
- 钓鱼(贪心+优先队列+重载运算符)
- C++优先队列(priority queue)及重载运算符
- 优先队列重载运算符< 以及初始化列表
- 关于STL中的优先队列
- 优先队列的重载方式。
- 关于运算符的重载
- Ajax处理缓存的方式
- vector的erase函数
- 怎样清理浏览器缓存[各种浏览器]
- merge-sorted-array
- C语言——泥塑课
- 关于stl优先队列重载小于运算符的问题
- <C++>析构函数、虚析构函数和构造函数
- Centos6.5集群安装mysql5.6和hive2.3
- Json拼接注意
- 元组Tuple
- Python 中的 super 用法
- 迭代输出Jquery对象
- Linux系统中软件安装的相关操作
- web前端关于浏览器兼容性