std::map排序的原理(这篇文章告诉我们多看看vs源码)

今天被同事问到一个问题,map中第三个参数的意思是什么,于是写了下面这个程序测试了一下。

  1. #include <map>  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. typedef map<int,char> icMap;  
  6. typedef map<int,char>::iterator It;  
  7.   
  8. class func  
  9. {  
  10. public:  
  11.     func(){};  
  12.     bool operator ()( const int i1, const int i2 )  
  13.     {  
  14.         return i1>i2;  
  15.     }  
  16. };  
  17.   
  18. typedef map<int,char,func> icMapCmp;  
  19. typedef map<int,char,func>::iterator It1;  
  20.   
  21. int main(void)  
  22. {  
  23.     icMap m;  
  24.     m.insert(make_pair(1,'1'));  
  25.     m.insert(make_pair(3,'3'));  
  26.     m.insert(make_pair(2,'2'));  
  27.   
  28.     for (It it = m.begin();it!=m.end();++it)  
  29.     {  
  30.         cout<<it->first<<"\t"<<it->second<<endl;  
  31.     }  
  32.   
  33.     icMapCmp c;  
  34.     c.insert(make_pair(1,'1'));  
  35.     c.insert(make_pair(3,'3'));  
  36.     c.insert(make_pair(2,'2'));  
  37.     for (It1 it1 = c.begin();it1!=c.end();++it1)  
  38.     {  
  39.         cout<<it1->first<<"\t"<<it1->second<<endl;  
  40.     }  
  41.   
  42.     return 0;  
  43. }  
#include <map>
#include <iostream>
using namespace std;

typedef map<int,char> icMap;
typedef map<int,char>::iterator It;

class func
{
public:
	func(){};
	bool operator ()( const int i1, const int i2 )
	{
		return i1>i2;
	}
};

typedef map<int,char,func> icMapCmp;
typedef map<int,char,func>::iterator It1;

int main(void)
{
	icMap m;
	m.insert(make_pair(1,'1'));
	m.insert(make_pair(3,'3'));
	m.insert(make_pair(2,'2'));

	for (It it = m.begin();it!=m.end();++it)
	{
		cout<<it->first<<"\t"<<it->second<<endl;
	}

	icMapCmp c;
	c.insert(make_pair(1,'1'));
	c.insert(make_pair(3,'3'));
	c.insert(make_pair(2,'2'));
	for (It1 it1 = c.begin();it1!=c.end();++it1)
	{
		cout<<it1->first<<"\t"<<it1->second<<endl;
	}

	return 0;
}


 

第三个参数MSDN的解释如下:

Traits

The type that provides a function object that can compare two element values as sort keys to determine their relative order in the map. This argument is optional and the binary predicate less<Key> is the default value.

MSDN上说的已经很清楚了,缺省的是 std::less

看stl_map.h中看map的定义:

 template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,

            typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >

class map

缺省的compare确实是std::less,std::less。在stl_function.h中std::less的实现如下:

扫描二维码关注公众号,回复: 51074 查看本文章
  1.  template <class _Tp>  
  2.     struct less : public binary_function<_Tp, _Tp, bool>  
  3.     {  
  4.       bool  
  5.       operator()(const _Tp& __x, const _Tp& __y) const  
  6.       { return __x < __y; }  
  7. };  
 template <class _Tp>
    struct less : public binary_function<_Tp, _Tp, bool>
    {
      bool
      operator()(const _Tp& __x, const _Tp& __y) const
      { return __x < __y; }
};


 

return __x < __y;原来如此。但是这仅仅是比较函数,比较了之后map又是如何处理的呢?好像还是没有找到根源。

那就继续追踪,map的构造函数:

      map()

      : _M_t(_Compare(), allocator_type()) { }

用_Compare()初始化了_M_t,那就继续追踪_M_t,追踪到了map内部的红黑树。

      typedef _Rb_tree<key_type, value_type, _Select1st<value_type>,

                     key_compare, _Pair_alloc_type> _Rep_type;

 

      /// @if maint  The actual tree structure.  @endif

      _Rep_type _M_t;

最后到了insert_unique函数中:

  1. template<typename _Key, typename _Val, typename _KeyOfValue,  
  2.           typename _Compare, typename _Alloc>  
  3.    pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,  
  4.            _Compare, _Alloc>::iterator, bool>  
  5.    _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::  
  6.    insert_unique(const _Val& __v)  
  7.    {  
  8.      _Link_type __x = _M_begin();  
  9.      _Link_type __y = _M_end();  
  10.      bool __comp = true;  
  11.      while (__x != 0)  
  12. {  
  13.   __y = __x;  
  14.   __comp = _M_impl._M_key_compare(_KeyOfValue()(__v), _S_key(__x));  
  15.   __x = __comp ? _S_left(__x) : _S_right(__x);  
  16. }  
  17.      iterator __j = iterator(__y);  
  18.      if (__comp)  
  19. if (__j == begin())  
  20.   return pair<iterator,bool>(_M_insert(__x, __y, __v), true);  
  21. else  
  22.   --__j;  
  23.      if (_M_impl._M_key_compare(_S_key(__j._M_node), _KeyOfValue()(__v)))  
  24. return pair<iterator, bool>(_M_insert(__x, __y, __v), true);  
  25.      return pair<iterator, bool>(__j, false);  
 template<typename _Key, typename _Val, typename _KeyOfValue,
           typename _Compare, typename _Alloc>
    pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,
			   _Compare, _Alloc>::iterator, bool>
    _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
    insert_unique(const _Val& __v)
    {
      _Link_type __x = _M_begin();
      _Link_type __y = _M_end();
      bool __comp = true;
      while (__x != 0)
	{
	  __y = __x;
	  __comp = _M_impl._M_key_compare(_KeyOfValue()(__v), _S_key(__x));
	  __x = __comp ? _S_left(__x) : _S_right(__x);
	}
      iterator __j = iterator(__y);
      if (__comp)
	if (__j == begin())
	  return pair<iterator,bool>(_M_insert(__x, __y, __v), true);
	else
	  --__j;
      if (_M_impl._M_key_compare(_S_key(__j._M_node), _KeyOfValue()(__v)))
	return pair<iterator, bool>(_M_insert(__x, __y, __v), true);
      return pair<iterator, bool>(__j, false);
}


 

函数前面的返回值类型定义有点复杂,其实就是返回pair<iterator, bool>的pair,然后根据要插入的值__v来比较,如果是真,就往左边找,否则就往右边找。

  1. template<typename _Key, typename _Val, typename _KeyOfValue,  
  2.           typename _Compare, typename _Alloc>  
  3.    typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator  
  4.    _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::  
  5.    _M_insert(_Base_ptr __x, _Base_ptr __p, const _Val& __v)  
  6.    {  
  7.      bool __insert_left = (__x != 0 || __p == _M_end()  
  8.             || _M_impl._M_key_compare(_KeyOfValue()(__v),   
  9.                           _S_key(__p)));  
  10.   
  11.      _Link_type __z = _M_create_node(__v);  
  12.   
  13.      _Rb_tree_insert_and_rebalance(__insert_left, __z, __p,    
  14.                 this->_M_impl._M_header);  
  15.      ++_M_impl._M_node_count;  
  16.      return iterator(__z);  
  17.    }  
 template<typename _Key, typename _Val, typename _KeyOfValue,
           typename _Compare, typename _Alloc>
    typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
    _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
    _M_insert(_Base_ptr __x, _Base_ptr __p, const _Val& __v)
    {
      bool __insert_left = (__x != 0 || __p == _M_end()
			    || _M_impl._M_key_compare(_KeyOfValue()(__v), 
						      _S_key(__p)));

      _Link_type __z = _M_create_node(__v);

      _Rb_tree_insert_and_rebalance(__insert_left, __z, __p,  
				    this->_M_impl._M_header);
      ++_M_impl._M_node_count;
      return iterator(__z);
    }


找到位置之后,创建节点,然后插入到二叉平衡树(也就是红黑树)中。

哈哈哈,_Rb_tree_insert_and_rebalance找不到代码。居然在STLPort里面找到了下面的代码。微笑

  1. template <class _Key, class _Value, class _KeyOfValue,   
  2.           class _Compare, class _Alloc> __iterator__   
  3. _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> ::_M_insert(_Rb_tree_node_base* __x_, _Rb_tree_node_base* __y_, const _Value& __v,  
  4.   _Rb_tree_node_base* __w_)  
  5. {  
  6.   _Link_type __w = (_Link_type) __w_;  
  7.   _Link_type __x = (_Link_type) __x_;  
  8.   _Link_type __y = (_Link_type) __y_;  
  9.   _Link_type __z;  
  10.   
  11.   if ( __y == this->_M_header._M_data ||  
  12.        ( __w == 0 && // If w != 0, the remainder fails to false  
  13.          ( __x != 0 ||     // If x != 0, the remainder succeeds to true  
  14.            _M_key_compare( _KeyOfValue()(__v), _S_key(__y) ) )  
  15.      )  
  16.        ) {  
  17.       
  18.     __z = _M_create_node(__v);  
  19.     _S_left(__y) = __z;               // also makes _M_leftmost() = __z   
  20.                                       //    when __y == _M_header  
  21.     if (__y == this->_M_header._M_data) {  
  22.       _M_root() = __z;  
  23.       _M_rightmost() = __z;  
  24.     }  
  25.     else if (__y == _M_leftmost())  
  26.       _M_leftmost() = __z;   // maintain _M_leftmost() pointing to min node  
  27.   }  
  28.   else {  
  29.     __z = _M_create_node(__v);  
  30.     _S_right(__y) = __z;  
  31.     if (__y == _M_rightmost())  
  32.       _M_rightmost() = __z;  // maintain _M_rightmost() pointing to max node  
  33.   }  
  34.   _S_parent(__z) = __y;  
  35.   _S_left(__z) = 0;  
  36.   _S_right(__z) = 0;  
  37.   _Rb_global_inst::_Rebalance(__z, this->_M_header._M_data->_M_parent);  
  38.   ++_M_node_count;  
  39.   return iterator(__z);  
  40. }  
template <class _Key, class _Value, class _KeyOfValue, 
          class _Compare, class _Alloc> __iterator__ 
_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> ::_M_insert(_Rb_tree_node_base* __x_, _Rb_tree_node_base* __y_, const _Value& __v,
  _Rb_tree_node_base* __w_)
{
  _Link_type __w = (_Link_type) __w_;
  _Link_type __x = (_Link_type) __x_;
  _Link_type __y = (_Link_type) __y_;
  _Link_type __z;

  if ( __y == this->_M_header._M_data ||
       ( __w == 0 && // If w != 0, the remainder fails to false
         ( __x != 0 ||     // If x != 0, the remainder succeeds to true
           _M_key_compare( _KeyOfValue()(__v), _S_key(__y) ) )
	 )
       ) {
    
    __z = _M_create_node(__v);
    _S_left(__y) = __z;               // also makes _M_leftmost() = __z 
                                      //    when __y == _M_header
    if (__y == this->_M_header._M_data) {
      _M_root() = __z;
      _M_rightmost() = __z;
    }
    else if (__y == _M_leftmost())
      _M_leftmost() = __z;   // maintain _M_leftmost() pointing to min node
  }
  else {
    __z = _M_create_node(__v);
    _S_right(__y) = __z;
    if (__y == _M_rightmost())
      _M_rightmost() = __z;  // maintain _M_rightmost() pointing to max node
  }
  _S_parent(__z) = __y;
  _S_left(__z) = 0;
  _S_right(__z) = 0;
  _Rb_global_inst::_Rebalance(__z, this->_M_header._M_data->_M_parent);
  ++_M_node_count;
  return iterator(__z);
}

猜你喜欢

转载自blog.csdn.net/oyhb_1992/article/details/80054545