map查找的问题,自定义结构体作为key,为什么只重载“<”就可以了
重载了“<”就知道如何比较两个结构就能排列啦
只用<号也能判断相等啊:
if( (!(a<b) && !(b<a) )
//ok,a==b
else
//a!=b
条款19:了解相等和等价的区别
STL充满了比较对象是否有同样的值。比如,当你用find来定位区间中第一个有特定值的对象的位置,find必须可以比较两个对象,看看一个的值是否与另一个相等。同样,当你尝试向set中插入一个新元素时,set::insert必须可以判断那个元素的值是否已经在set中了。
find算法和set的insert成员函数是很多必须判断两个值是否相同的函数的代表。但它们以不同的方式完成,find对“相同”的定义是相等,基于operator==。set::insert对“相同”的定义是等价,通常基于operator<。因为有定义不同,所以有可能一个定义规定了两个对象有相同的值而另一个定义判定它们没有。结果,如果你想有效使用STL,那么你必须明白相等和等价的区别。
问题:
不用“==”,只用“<”就可以判断两个对象是否相等。但是在楼上的文章中写到, map 中判断相等是给予“==”的。 又把握搞糊涂了。
解疑:
(1)成员函数map.find调用的是等价,也就是!c.key_comp()(x, y) && !c.key_comp()(y, x),
算法find调用的是相等,如find(map.begin(), map.end(), a),调用的是对相等的operator ==
(2)find其实有两个,一个是算法的find,一个是map成员的find,而你调用的是成员的。成员的find是靠“<”,泛型算法的find靠的是"=="。
算法的find,类似find(map.begin(), map.end(), a)这种形式
你调用的find函数是Map的成员函数,类似map.find(a)这种形式,它只需要operator < 就够了
在map的实现里面就是靠 对调operator<两边的操作数实现的。
set的源码如下:
_Nodeptr _Lbound(const _K& _Kv) const
{_Nodeptr _X = _Root();
_Nodeptr _Y = _Head;
while (_X != _Nil)
if (key_compare(_Key(_X), _Kv)) //就是operator<调用的地方
_X = _Right(_X); //往右边子树走
else
_Y = _X, _X = _Left(_X); //记录父节点,往左边子树走
return (_Y); }
iterator find(const _K& _Kv)
{iterator _P = lower_bound(_Kv); //这个_P就是_Lbound返回的_Y
return (_P == end()
|| key_compare(_Kv, _Key(_P._Mynode())) //把_P再和_Kv对调了比较一下
? end() : _P); }
_Kv就是键值,注意_LBound里面,_Kv都是在后面来比较的,而find里面,最后还放在前面比较了一下,可以==就是靠两次<来完成比较的。
Map.find源码,成员函数map.find调用方式
iterator find(const key_type& _Keyval)
{ // find an element in mutable sequence that matches _Keyval(在可变序列中查找与_Keyval匹配的元素)
iterator _Where = lower_bound(_Keyval);
return (_Where == end()
|| _DEBUG_LT_PRED(this->_Getcomp(),
_Keyval, this->_Key(_Where._Mynode()))
? end() : _Where);
}
iterator lower_bound(const key_type& _Keyval)
{ // find leftmost node not less than _Keyval in mutable tree(在可变树中找到不小于_Keyval的最左节点)
return (iterator(_Lbound(_Keyval), this));
}
_Nodeptr _Lbound(const key_type& _Keyval)
{ // find leftmost node not less than _Keyval(找到不小于Keyval的最左节点)
_Nodeptr _Pnode = _Root();
_Nodeptr _Wherenode = this->_Myhead; // end() if search fails
while (!this->_Isnil(_Pnode))
if (_DEBUG_LT_PRED(this->_Getcomp(), this->_Key(_Pnode), _Keyval))
_Pnode = this->_Right(_Pnode); // descend right subtree(往右边子树走)
else
{ // _Pnode not less than _Keyval, remember it(Pnode不小于Keyval,记住它)
_Wherenode = _Pnode;
_Pnode = this->_Left(_Pnode); // descend left subtree(往左边子树走)
}
return (_Wherenode); // return best remembered candidate
}
stl map 使用结构体作为键,demo举例:
#include <iostream>
#include <map>
#include <string>
using namespace std;
struct package
{
int id;
string data;
bool operator<(const package& tmp) const{
if(this->id < tmp.id)
return true; //自定义排序规则
return false;
}
};
int main() {
map<package,int> tmp;
package a = {3,"a"};
package b = {2,"b"};
tmp.insert(make_pair(a, 0));
tmp.insert(make_pair(b, 0)); //插入
map<package, int>::iterator i;
for(i = tmp.begin(); i != tmp.end(); i++)
cout << i->first.id << " " << i->first.data << " " << i->second << endl;
}