参考博客:c++ map find方法源码解析
众所周知,如果一个数据结构想作为map的key,则必须重载 operator <
否则编译将会报错。但是operator ==
则是不需要的。那么当查找某个key是否存在的时候,map内部是怎么实现的呢?
结论
为了方便理解,先给出结论(map数据结构红黑树
):
1.查找最接近但不小于指定key的节点,并返回该节点,如果该节点不存在则返回end。
2.如果当前节点不是end则将指定的key和当前节点比较。如果返回false则该节点就是我们需要查找的节点,如果返回true,则表示没找到。
示例1:查找key=3的节点,返回5非end,此时将指定key和当前节点比较,即3 < 5,返回True,表示没找到指定节点。
示例2:查找key=7的节点,返回7非end,此时将指定key和当前节点比较,即7 < 7,返回false,表示找到指定节点。
示例3:查找key=9的节点,返回end,表示没找到指定节点。
下面是map源码:
_NODISCARD iterator find(const key_type& _Keyval) {
return iterator(_Find(_Keyval), _Get_scary());
}
template <class _Other>
_NODISCARD _Nodeptr _Find(const _Other& _Keyval) const {
const _Tree_find_result<_Nodeptr> _Loc = _Find_lower_bound(_Keyval);
if (_Lower_bound_duplicate(_Loc._Bound, _Keyval)) {
return _Loc._Bound;
}
return _Get_scary()->_Myhead;
}
查找最接近但不小于指定key的节点_Find_lower_bound
template <class _Keyty>
_Tree_find_result<_Nodeptr> _Find_lower_bound(const _Keyty& _Keyval) const {
const auto _Scary = _Get_scary();
_Tree_find_result<_Nodeptr> _Result{{_Scary->_Myhead->_Parent, _Tree_child::_Right}, _Scary->_Myhead};
_Nodeptr _Trynode = _Result._Location._Parent;
while (!_Trynode->_Isnil) {
_Result._Location._Parent = _Trynode;
if (_DEBUG_LT_PRED(_Getcomp(), _Traits::_Kfn(_Trynode->_Myval), _Keyval)) {
_Result._Location._Child = _Tree_child::_Right;
_Trynode = _Trynode->_Right;
} else {
_Result._Location._Child = _Tree_child::_Left;
_Result._Bound = _Trynode;
_Trynode = _Trynode->_Left;
}
}
return _Result;
}
如果当前节点不是end则将指定的key和当前节点比较。如果返回false则该节点就是我们需要查找的节点,如果返回true,则表示没找到_Lower_bound_duplicate
template <class _Keyty>
bool _Lower_bound_duplicate(const _Nodeptr _Bound, const _Keyty& _Keyval) const {
return !_Bound->_Isnil && !_DEBUG_LT_PRED(_Getcomp(), _Keyval, _Traits::_Kfn(_Bound->_Myval));
}
不同版本的stl库的源码实现可能存在差异,但是原理都是相同的。