C ++ (STL source code): 28 --- associative container set, map source analysis

A, set

Characteristic set of

  • The key set all elements are automatically sorted elements
  • The key is set in the real-valued, the real value is the key
  • By default, the set does not permit two elements repeat

set iterator

  • Changing the value of the set element is set according to the iterator. Because it is the real key value, the real value is the key, if you change the set element value, would seriously undermine the organization set
  • We will see later in the source code, set the iterator set <T> :: iterator is defined as the RB-tree const_iterator bottom. So set iterator is a constant iterators

have the same set certain properties of the list

  • When a new client to its elemental (insert) operation or delete (erase) operation, all iterators before the operation is still valid after the operation is completed (of course, the iterator to remove that element is invalid)

Correlation algorithm

  • Providing a set of STL set / multiset related algorithms, including intersection (set_intersection), union (set_union), difference set (set_difference), symmetric difference (set_symmetric_difference)
  • Details will be explained later in the "algorithm" article

set substructure

  • Since the RB-tree is a balanced binary search tree, automatic sorting effect is very good, so the standard STL set is RB-tree is the underlying mechanism
  • Also, because the set of open interfaces of various operations, RB-tree are also provided, so almost all of the set operation behavior, just turn calls the operating behavior of the RB-tree it
  • RB-tree See: https://blog.csdn.net/qq_41453285/article/details/103645839

set source

  • The following is a set of source code excerpt
//代码摘录于stl_set.h
template <class _Key, class _Compare, class _Alloc>
class set {
  // requirements:

  __STL_CLASS_REQUIRES(_Key, _Assignable);
  __STL_CLASS_BINARY_FUNCTION_CHECK(_Compare, bool, _Key, _Key);

public:
  // typedefs:

  typedef _Key     key_type;
  typedef _Key     value_type;
  typedef _Compare key_compare;
  typedef _Compare value_compare;
private:
  typedef _Rb_tree<key_type, value_type, 
                  _Identity<value_type>, key_compare, _Alloc> _Rep_type;
  _Rep_type _M_t;  // 采用红黑树来表现set
public:
  typedef typename _Rep_type::const_pointer pointer;
  typedef typename _Rep_type::const_pointer const_pointer;
  typedef typename _Rep_type::const_reference reference;
  typedef typename _Rep_type::const_reference const_reference;
  typedef typename _Rep_type::const_iterator iterator;
  //注意上一行,iterator定义为RB-tree的const_iterator,表示
  //set的迭代器无法执行写入操作
  typedef typename _Rep_type::const_iterator const_iterator;
  typedef typename _Rep_type::const_reverse_iterator reverse_iterator;
  typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
  typedef typename _Rep_type::size_type size_type;
  typedef typename _Rep_type::difference_type difference_type;
  typedef typename _Rep_type::allocator_type allocator_type;

  // allocation/deallocation
  //注意,set一定使用RB-=tree的insert_unique()而非insert_equal()
  //multiset才使用RB-tree的insert_equal()
  set() : _M_t(_Compare(), allocator_type()) {}
  explicit set(const _Compare& __comp,
               const allocator_type& __a = allocator_type())
    : _M_t(__comp, __a) {}

#ifdef __STL_MEMBER_TEMPLATES
  template <class _InputIterator>
  set(_InputIterator __first, _InputIterator __last)
    : _M_t(_Compare(), allocator_type())
    { _M_t.insert_unique(__first, __last); }

  template <class _InputIterator>
  set(_InputIterator __first, _InputIterator __last, const _Compare& __comp,
      const allocator_type& __a = allocator_type())
    : _M_t(__comp, __a) { _M_t.insert_unique(__first, __last); }
#else
  set(const value_type* __first, const value_type* __last) 
    : _M_t(_Compare(), allocator_type()) 
    { _M_t.insert_unique(__first, __last); }

  set(const value_type* __first, 
      const value_type* __last, const _Compare& __comp,
      const allocator_type& __a = allocator_type())
    : _M_t(__comp, __a) { _M_t.insert_unique(__first, __last); }

  set(const_iterator __first, const_iterator __last)
    : _M_t(_Compare(), allocator_type()) 
    { _M_t.insert_unique(__first, __last); }

  set(const_iterator __first, const_iterator __last, const _Compare& __comp,
      const allocator_type& __a = allocator_type())
    : _M_t(__comp, __a) { _M_t.insert_unique(__first, __last); }
#endif /* __STL_MEMBER_TEMPLATES */

  set(const set<_Key,_Compare,_Alloc>& __x) : _M_t(__x._M_t) {}
  set<_Key,_Compare,_Alloc>& operator=(const set<_Key, _Compare, _Alloc>& __x)
  { 
    _M_t = __x._M_t; 
    return *this;
  }

  //以下所有的set操作,RB-tree都已提供,所以set只要传递调用即可
  // accessors:

  key_compare key_comp() const { return _M_t.key_comp(); }
  value_compare value_comp() const { return _M_t.key_comp(); }
  allocator_type get_allocator() const { return _M_t.get_allocator(); }

  iterator begin() const { return _M_t.begin(); }
  iterator end() const { return _M_t.end(); }
  reverse_iterator rbegin() const { return _M_t.rbegin(); } 
  reverse_iterator rend() const { return _M_t.rend(); }
  bool empty() const { return _M_t.empty(); }
  size_type size() const { return _M_t.size(); }
  size_type max_size() const { return _M_t.max_size(); }
  void swap(set<_Key,_Compare,_Alloc>& __x) { _M_t.swap(__x._M_t); }

  // insert/erase
  pair<iterator,bool> insert(const value_type& __x) { 
    pair<typename _Rep_type::iterator, bool> __p = _M_t.insert_unique(__x); 
    return pair<iterator, bool>(__p.first, __p.second);
  }
  iterator insert(iterator __position, const value_type& __x) {
    typedef typename _Rep_type::iterator _Rep_iterator;
    return _M_t.insert_unique((_Rep_iterator&)__position, __x);
  }
#ifdef __STL_MEMBER_TEMPLATES
  template <class _InputIterator>
  void insert(_InputIterator __first, _InputIterator __last) {
    _M_t.insert_unique(__first, __last);
  }
#else
  void insert(const_iterator __first, const_iterator __last) {
    _M_t.insert_unique(__first, __last);
  }
  void insert(const value_type* __first, const value_type* __last) {
    _M_t.insert_unique(__first, __last);
  }
#endif /* __STL_MEMBER_TEMPLATES */
  void erase(iterator __position) { 
    typedef typename _Rep_type::iterator _Rep_iterator;
    _M_t.erase((_Rep_iterator&)__position); 
  }
  size_type erase(const key_type& __x) { 
    return _M_t.erase(__x); 
  }
  void erase(iterator __first, iterator __last) { 
    typedef typename _Rep_type::iterator _Rep_iterator;
    _M_t.erase((_Rep_iterator&)__first, (_Rep_iterator&)__last); 
  }
  void clear() { _M_t.clear(); }

  // set operations:

  iterator find(const key_type& __x) const { return _M_t.find(__x); }
  size_type count(const key_type& __x) const {
    return _M_t.find(__x) == _M_t.end() ? 0 : 1;
  }
  iterator lower_bound(const key_type& __x) const {
    return _M_t.lower_bound(__x);
  }
  iterator upper_bound(const key_type& __x) const {
    return _M_t.upper_bound(__x); 
  }
  pair<iterator,iterator> equal_range(const key_type& __x) const {
    return _M_t.equal_range(__x);
  }

#ifdef __STL_TEMPLATE_FRIENDS
  template <class _K1, class _C1, class _A1>
  friend bool operator== (const set<_K1,_C1,_A1>&, const set<_K1,_C1,_A1>&);
  template <class _K1, class _C1, class _A1>
  friend bool operator< (const set<_K1,_C1,_A1>&, const set<_K1,_C1,_A1>&);
#else /* __STL_TEMPLATE_FRIENDS */
  friend bool __STD_QUALIFIER
  operator== __STL_NULL_TMPL_ARGS (const set&, const set&);
  friend bool __STD_QUALIFIER
  operator<  __STL_NULL_TMPL_ARGS (const set&, const set&);
#endif /* __STL_TEMPLATE_FRIENDS */
};

set of use cases

#include <iostream>
#include <set>
using namespace std;

int main()
{
	int i;
	int ia[5] = { 0,1,2,3,4 };
	set<int> iset(ia,ia+5);
	std::cout << "size=" << iset.size() << std::endl;
	std::cout << "3 count" << iset.count(3) << std::endl << std::endl;

	iset.insert(3);
	std::cout << "size=" << iset.size() << std::endl;
	std::cout << "3 count" << iset.count(3) << std::endl << std::endl;

	iset.insert(5);
	std::cout << "size=" << iset.size() << std::endl;
	std::cout << "3 count" << iset.count(3) << std::endl << std::endl;

	iset.erase(1);
	std::cout << "size=" << iset.size() << std::endl;
	std::cout << "3 count" << iset.count(3) << std::endl;
	std::cout << "1 count" << iset.count(1) << std::endl << std::endl;

	set<int>::iterator ite1 = iset.begin();
	set<int>::iterator ite2 = iset.end();
	for (; ite1 != ite2; ite1++)
		std::cout << *ite1<<" ";
	std::cout << std::endl << std::endl;

	//使用STL算法来搜寻元素(循环搜索的),但是没有set的内置find函数高效
	ite1 = find(iset.begin(), iset.end(), 3);
	if (ite1 != iset.end())
		std::cout << "3 found" << std::endl;
	else
		std::cout << "3 not found" << std::endl << std::endl;

	//使用set的内置find函数,比STL算法高效
	ite1 = iset.find(1);
	if (ite1 != iset.end())
		std::cout << "1 found" << std::endl;
	else
		std::cout << "1 not found" << std::endl << std::endl;

	//*ite1 = 9;  错误,不能通过set的迭代器来改变元素的值
	return 0;
}

Two, map

The characteristic map

  • All the elements are automatically sorted according to key elements

pair in the map structure

  • All types of map elements are pair, have both real value (value) and key (key)
  • Regarded as the first element of a pair of keys, the second element as real value
  • map does not permit two elements have the same key
  • Here is the definition of the pair of stl_pair.h:
//代码摘录与stl_pair.h
template <class _T1, class _T2>
struct pair {
  typedef _T1 first_type;
  typedef _T2 second_type;

  _T1 first;
  _T2 second;
  pair() : first(_T1()), second(_T2()) {}
  pair(const _T1& __a, const _T2& __b) : first(__a), second(__b) {}

#ifdef __STL_MEMBER_TEMPLATES
  template <class _U1, class _U2>
  pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {}
#endif
};

map iterators

  • The key can not change the map node iterator, but may be changed by a real-valued nodes map the iterator
  • Thus, map iterators neither a constant iterators, nor is it a mutable iterators

Some properties have the same map and list of

  • When a new client to its elemental (insert) operation or delete (erase) operation, all iterators before the operation is still valid after the operation is completed (of course, the iterator to remove that element is invalid)

Map of the underlying structure

  • Since the RB-tree is a balanced binary search tree, automatic sorting effect is very good, so the standard STL map is RB-tree is the underlying mechanism
  • Also, because the map of the various operations open interfaces, RB-tree are also provided, so almost all of the map operation behavior, just turn calls the operating behavior of the RB-tree it
  • RB-tree See: https://blog.csdn.net/qq_41453285/article/details/103645839
  • The following is a map of the structure:

map source

  • The following is a map of the source code excerpt
//代码摘录与stl_map.h
template <class _Key, class _Tp, class _Compare, class _Alloc>
class map {
public:

// requirements:

  __STL_CLASS_REQUIRES(_Tp, _Assignable);
  __STL_CLASS_BINARY_FUNCTION_CHECK(_Compare, bool, _Key, _Key);

// typedefs:

  typedef _Key                  key_type;  //键值类型
  typedef _Tp                   data_type; //数据(实值)类型
  typedef _Tp                   mapped_type;
  typedef pair<const _Key, _Tp> value_type; //元素类型(键值/实值)
  typedef _Compare              key_compare; //键值比较函数
    
  //以下定义一个functor,作用就是调用“元素比较函数”
  class value_compare
    : public binary_function<value_type, value_type, bool> {
  friend class map<_Key,_Tp,_Compare,_Alloc>;
  protected :
    _Compare comp;
    value_compare(_Compare __c) : comp(__c) {}
  public:
    bool operator()(const value_type& __x, const value_type& __y) const {
      return comp(__x.first, __y.first);
    }
  };

private:
  //以下定义表述类型。以map元素类型(一个pair)的第一类型,作为RB-tree节点的键值类型
  typedef _Rb_tree<key_type, value_type, 
                   _Select1st<value_type>, key_compare, _Alloc> _Rep_type;
  _Rep_type _M_t;  // 以红黑树实现map
public:
  typedef typename _Rep_type::pointer pointer;
  typedef typename _Rep_type::const_pointer const_pointer;
  typedef typename _Rep_type::reference reference;
  typedef typename _Rep_type::const_reference const_reference;
  typedef typename _Rep_type::iterator iterator;
  //注意上面一行,map不像set,map使用的是RB-tree的iterator
  typedef typename _Rep_type::const_iterator const_iterator;
  typedef typename _Rep_type::reverse_iterator reverse_iterator;
  typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
  typedef typename _Rep_type::size_type size_type;
  typedef typename _Rep_type::difference_type difference_type;
  typedef typename _Rep_type::allocator_type allocator_type;

  //注意,map一定使用底层RB-tree的insert_unique()而非insert_equal()
  //multimap才使用insert_equal()
  // allocation/deallocation

  map() : _M_t(_Compare(), allocator_type()) {}
  explicit map(const _Compare& __comp,
               const allocator_type& __a = allocator_type())
    : _M_t(__comp, __a) {}

#ifdef __STL_MEMBER_TEMPLATES
  template <class _InputIterator>
  map(_InputIterator __first, _InputIterator __last)
    : _M_t(_Compare(), allocator_type())
    { _M_t.insert_unique(__first, __last); }

  template <class _InputIterator>
  map(_InputIterator __first, _InputIterator __last, const _Compare& __comp,
      const allocator_type& __a = allocator_type())
    : _M_t(__comp, __a) { _M_t.insert_unique(__first, __last); }
#else
  map(const value_type* __first, const value_type* __last)
    : _M_t(_Compare(), allocator_type())
    { _M_t.insert_unique(__first, __last); }

  map(const value_type* __first,
      const value_type* __last, const _Compare& __comp,
      const allocator_type& __a = allocator_type())
    : _M_t(__comp, __a) { _M_t.insert_unique(__first, __last); }

  map(const_iterator __first, const_iterator __last)
    : _M_t(_Compare(), allocator_type()) 
    { _M_t.insert_unique(__first, __last); }

  map(const_iterator __first, const_iterator __last, const _Compare& __comp,
      const allocator_type& __a = allocator_type())
    : _M_t(__comp, __a) { _M_t.insert_unique(__first, __last); }

#endif /* __STL_MEMBER_TEMPLATES */

  map(const map<_Key,_Tp,_Compare,_Alloc>& __x) : _M_t(__x._M_t) {}
  map<_Key,_Tp,_Compare,_Alloc>&
  operator=(const map<_Key, _Tp, _Compare, _Alloc>& __x)
  {
    _M_t = __x._M_t;
    return *this; 
  }

  //以下所有mao操作,RB-tree都已提供,mao只要调用即可
  // accessors:

  key_compare key_comp() const { return _M_t.key_comp(); }
  value_compare value_comp() const { return value_compare(_M_t.key_comp()); }
  allocator_type get_allocator() const { return _M_t.get_allocator(); }

  iterator begin() { return _M_t.begin(); }
  const_iterator begin() const { return _M_t.begin(); }
  iterator end() { return _M_t.end(); }
  const_iterator end() const { return _M_t.end(); }
  reverse_iterator rbegin() { return _M_t.rbegin(); }
  const_reverse_iterator rbegin() const { return _M_t.rbegin(); }
  reverse_iterator rend() { return _M_t.rend(); }
  const_reverse_iterator rend() const { return _M_t.rend(); }
  bool empty() const { return _M_t.empty(); }
  size_type size() const { return _M_t.size(); }
  size_type max_size() const { return _M_t.max_size(); }
  _Tp& operator[](const key_type& __k) {
    iterator __i = lower_bound(__k);
    // __i->first is greater than or equivalent to __k.
    if (__i == end() || key_comp()(__k, (*__i).first))
      __i = insert(__i, value_type(__k, _Tp()));
    return (*__i).second;
  }
  void swap(map<_Key,_Tp,_Compare,_Alloc>& __x) { _M_t.swap(__x._M_t); }

  // insert/erase

  pair<iterator,bool> insert(const value_type& __x) 
    { return _M_t.insert_unique(__x); }
  iterator insert(iterator position, const value_type& __x)
    { return _M_t.insert_unique(position, __x); }
#ifdef __STL_MEMBER_TEMPLATES
  template <class _InputIterator>
  void insert(_InputIterator __first, _InputIterator __last) {
    _M_t.insert_unique(__first, __last);
  }
#else
  void insert(const value_type* __first, const value_type* __last) {
    _M_t.insert_unique(__first, __last);
  }
  void insert(const_iterator __first, const_iterator __last) {
    _M_t.insert_unique(__first, __last);
  }
#endif /* __STL_MEMBER_TEMPLATES */

  void erase(iterator __position) { _M_t.erase(__position); }
  size_type erase(const key_type& __x) { return _M_t.erase(__x); }
  void erase(iterator __first, iterator __last)
    { _M_t.erase(__first, __last); }
  void clear() { _M_t.clear(); }

  // map operations:

  iterator find(const key_type& __x) { return _M_t.find(__x); }
  const_iterator find(const key_type& __x) const { return _M_t.find(__x); }
  size_type count(const key_type& __x) const {
    return _M_t.find(__x) == _M_t.end() ? 0 : 1; 
  }
  iterator lower_bound(const key_type& __x) {return _M_t.lower_bound(__x); }
  const_iterator lower_bound(const key_type& __x) const {
    return _M_t.lower_bound(__x); 
  }
  iterator upper_bound(const key_type& __x) {return _M_t.upper_bound(__x); }
  const_iterator upper_bound(const key_type& __x) const {
    return _M_t.upper_bound(__x); 
  }
  
  pair<iterator,iterator> equal_range(const key_type& __x) {
    return _M_t.equal_range(__x);
  }
  pair<const_iterator,const_iterator> equal_range(const key_type& __x) const {
    return _M_t.equal_range(__x);
  }

#ifdef __STL_TEMPLATE_FRIENDS 
  template <class _K1, class _T1, class _C1, class _A1>
  friend bool operator== (const map<_K1, _T1, _C1, _A1>&,
                          const map<_K1, _T1, _C1, _A1>&);
  template <class _K1, class _T1, class _C1, class _A1>
  friend bool operator< (const map<_K1, _T1, _C1, _A1>&,
                         const map<_K1, _T1, _C1, _A1>&);
#else /* __STL_TEMPLATE_FRIENDS */
  friend bool __STD_QUALIFIER
  operator== __STL_NULL_TMPL_ARGS (const map&, const map&);
  friend bool __STD_QUALIFIER
  operator< __STL_NULL_TMPL_ARGS (const map&, const map&);
#endif /* __STL_TEMPLATE_FRIENDS */
};
  • insert function:
    • Pair return type. pair return a parameter elements, the second parameter is BOOL, indicating whether or not successfully inserted. Insert successful pair parameter 1 only to save the node are returned
    • RB-tree to the bottom of insert_unique to perform
pair<iterator,bool> insert(const value_type& __x) 
    { return _M_t.insert_unique(__x); }
  • Subscript operator ([]):
    • Left values ​​using: the contents can be modified
    • Right use of value: the content can not be modified
map<std::string, int> simap;
simap[std::string("dongshao")] = 1;         //左值运用
int number = simap[std::string("dongshao")];//右值运用
  • Subscript operator is defined as follows

map use cases

#include <iostream>
#include <string>
#include <map>
#include <utility>
using namespace std;

int main()
{
	map<std::string, int> simap;
	simap[std::string("jjhou")] = 1;
	simap[std::string("jerry")] = 2;
	simap[std::string("jason")] = 3;
	simap[std::string("jimmy")] = 4;

	std::pair<std::string, int> value(std::string("david"), 5);
	simap.insert(value);

	map<std::string, int>::iterator simap_iter = simap.begin();
	for (; simap_iter != simap.end(); simap_iter++)
		std::cout << simap_iter->first << ": " << simap_iter->second << std::endl;
	std::cout << std::endl;

	int number = simap[std::string("jjhou")];
	std::cout << number << std::endl << std::endl;


	map<std::string, int>::iterator iter;
	iter = simap.find(std::string("mchen"));
	if (iter != simap.end())
		std::cout << "mchen found" << std::endl;
	else
		std::cout << "mchen not found" << std::endl;
	iter = simap.find(std::string("jerry"));
	if (iter != simap.end())
		std::cout << "jerry found" << std::endl;
	else
		std::cout << "jerry not found" << std::endl;
	std::cout << std::endl;

	iter->second = 9;
	int number2 = simap[std::string("jerry")];
	std::cout << number2 << std::endl;
	return 0;
}

 

发布了1463 篇原创文章 · 获赞 996 · 访问量 35万+

Guess you like

Origin blog.csdn.net/qq_41453285/article/details/104249771