std::map源码分析

来源:互联网 发布:单片机课程设计目的 编辑:程序博客网 时间:2024/06/07 13:00

默认构造的时候 初始化:

void _Init(){// create head/nil node and make tree empty_Myhead = _Buynode();_Isnil(_Myhead) = true;_Root() = _Myhead;_Lmost() = _Myhead, _Rmost() = _Myhead;_Mysize = 0;}

首先会分配头结点的内存:

_Nodeptr _Buynode(){// allocate a head/nil node_Nodeptr _Wherenode = this->_Alnod.allocate(1);int _Linkcnt = 0;_TRY_BEGINthis->_Alptr.construct(&_Left(_Wherenode), 0);++_Linkcnt;this->_Alptr.construct(&_Parent(_Wherenode), 0);++_Linkcnt;this->_Alptr.construct(&_Right(_Wherenode), 0);_CATCH_ALLif (1 < _Linkcnt)this->_Alptr.destroy(&_Parent(_Wherenode));if (0 < _Linkcnt)this->_Alptr.destroy(&_Left(_Wherenode));this->_Alnod.deallocate(_Wherenode, 1);_RERAISE;_CATCH_END_Color(_Wherenode) = _Black;_Isnil(_Wherenode) = false;return (_Wherenode);}

然后设置颜色为black;设置根节点和最左、最右节点。

2、operator[]操作的时候:

mapped_type& operator[](const key_type& _Keyval){// find element matching _Keyval or insert with default mappediterator _Where = this->lower_bound(_Keyval);if (_Where == this->end()|| this->comp(_Keyval, this->_Key(_Where._Mynode())))_Where = this->insert(_Where,value_type(_Keyval, mapped_type()));return ((*_Where).second);}

第一次插入的,时候lower_bound返回头结点,因为tree是空;

_Where == this->end()为真,执行

_Where = this->insert(_Where,
value_type(_Keyval, mapped_type()));

之后会执行:

iterator insert(const_iterator _Where,const value_type& _Val){// try to insert node with value _Val using _Where as a hint #if _HAS_ITERATOR_DEBUGGINGif (_Where._Mycont != this)_DEBUG_ERROR("map/set insert iterator outside range"); #endif /* _HAS_ITERATOR_DEBUGGING */const_iterator _Next;if (size() == 0)return (_Insert(true, _Myhead, _Val));// insert into empty treeelse if (this->_Multi){// insert even if duplicateif (_Where == begin()){// insert at beginning if before first elementif (!_DEBUG_LT_PRED(this->comp,_Key(_Where._Mynode()), this->_Kfn(_Val)))return (_Insert(true, _Where._Mynode(), _Val));}else if (_Where == end()){// insert at end if after last elementif (!_DEBUG_LT_PRED(this->comp,this->_Kfn(_Val), _Key(_Rmost())))return (_Insert(false, _Rmost(), _Val));}else if (!_DEBUG_LT_PRED(this->comp,_Key(_Where._Mynode()), this->_Kfn(_Val))&& !_DEBUG_LT_PRED(this->comp,this->_Kfn(_Val), _Key((--(_Next = _Where))._Mynode()))){// insert before _Whereif (_Isnil(_Right(_Next._Mynode())))return (_Insert(false, _Next._Mynode(), _Val));elsereturn (_Insert(true, _Where._Mynode(), _Val));}else if (!_DEBUG_LT_PRED(this->comp,this->_Kfn(_Val), _Key(_Where._Mynode()))&& (++(_Next = _Where) == end()|| !_DEBUG_LT_PRED(this->comp,_Key(_Next._Mynode()), this->_Kfn(_Val)))){// insert after _Whereif (_Isnil(_Right(_Where._Mynode())))return (_Insert(false, _Where._Mynode(), _Val));elsereturn (_Insert(true, _Next._Mynode(), _Val));}}else{// insert only if uniqueif (_Where == begin()){// insert at beginning if before first elementif (_DEBUG_LT_PRED(this->comp,this->_Kfn(_Val), _Key(_Where._Mynode())))return (_Insert(true, _Where._Mynode(), _Val));}else if (_Where == end()){// insert at end if after last elementif (_DEBUG_LT_PRED(this->comp,_Key(_Rmost()), this->_Kfn(_Val)))return (_Insert(false, _Rmost(), _Val));}else if (_DEBUG_LT_PRED(this->comp,this->_Kfn(_Val), _Key(_Where._Mynode()))&& _DEBUG_LT_PRED(this->comp,_Key((--(_Next = _Where))._Mynode()), this->_Kfn(_Val))){// insert before _Whereif (_Isnil(_Right(_Next._Mynode())))return (_Insert(false, _Next._Mynode(), _Val));elsereturn (_Insert(true, _Where._Mynode(), _Val));}else if (_DEBUG_LT_PRED(this->comp,_Key(_Where._Mynode()), this->_Kfn(_Val))&& (++(_Next = _Where) == end()|| _DEBUG_LT_PRED(this->comp,this->_Kfn(_Val), _Key(_Next._Mynode())))){// insert after _Whereif (_Isnil(_Right(_Where._Mynode())))return (_Insert(false, _Where._Mynode(), _Val));elsereturn (_Insert(true, _Next._Mynode(), _Val));}}return (insert(_Val).first);// try usual insert if all else fails}

因为if (size() == 0)为真

所以

iterator _Insert(bool _Addleft, _Nodeptr _Wherenode,const value_type& _Val){// add node with value next to _Wherenode, to left if _Addnodeif (max_size() - 1 <= _Mysize)_THROW(length_error, "map/set<T> too long");_Nodeptr _Newnode = _Buynode(_Myhead, _Wherenode, _Myhead,_Val, _Red);++_Mysize;if (_Wherenode == _Myhead){// first node in tree, just set head values_Root() = _Newnode;_Lmost() = _Newnode, _Rmost() = _Newnode;}else if (_Addleft){// add to left of _Wherenode_Left(_Wherenode) = _Newnode;if (_Wherenode == _Lmost())_Lmost() = _Newnode;}else{// add to right of _Wherenode_Right(_Wherenode) = _Newnode;if (_Wherenode == _Rmost())_Rmost() = _Newnode;}for (_Nodeptr _Pnode = _Newnode; _Color(_Parent(_Pnode)) == _Red; )if (_Parent(_Pnode) == _Left(_Parent(_Parent(_Pnode)))){// fixup red-red in left subtree_Wherenode = _Right(_Parent(_Parent(_Pnode)));if (_Color(_Wherenode) == _Red){// parent has two red children, blacken both_Color(_Parent(_Pnode)) = _Black;_Color(_Wherenode) = _Black;_Color(_Parent(_Parent(_Pnode))) = _Red;_Pnode = _Parent(_Parent(_Pnode));}else{// parent has red and black childrenif (_Pnode == _Right(_Parent(_Pnode))){// rotate right child to left_Pnode = _Parent(_Pnode);_Lrotate(_Pnode);}_Color(_Parent(_Pnode)) = _Black;// propagate red up_Color(_Parent(_Parent(_Pnode))) = _Red;_Rrotate(_Parent(_Parent(_Pnode)));}}else{// fixup red-red in right subtree_Wherenode = _Left(_Parent(_Parent(_Pnode)));if (_Color(_Wherenode) == _Red){// parent has two red children, blacken both_Color(_Parent(_Pnode)) = _Black;_Color(_Wherenode) = _Black;_Color(_Parent(_Parent(_Pnode))) = _Red;_Pnode = _Parent(_Parent(_Pnode));}else{// parent has red and black childrenif (_Pnode == _Left(_Parent(_Pnode))){// rotate left child to right_Pnode = _Parent(_Pnode);_Rrotate(_Pnode);}_Color(_Parent(_Pnode)) = _Black;// propagate red up_Color(_Parent(_Parent(_Pnode))) = _Red;_Lrotate(_Parent(_Parent(_Pnode)));}}_Color(_Root()) = _Black;// root is always blackreturn (_TREE_ITERATOR(_Newnode));}

直接插进去了。

[]操作类似一个find操作,如果没有,就分配一个node放在正确的位置,分配颜色, 然后把迭代器的第二个值引用返回,然后再设置。

如果存在,就修改呗。擦擦擦,就是酱紫。

2、如果这样insert的时候:

    MyMap testMap;    testMap.insert(std::make_pair(1,2));    testMap.insert(std::make_pair(1,4));

第二次就会失败,因为它会先查找到应该插入的地方的上一个节点,如果key相等,就return (_Pairib(_Where, false));

所以不会插入滴。好吧,昨天被同事指出这段代码的问题,今天终于把代码看了下!!


0 0