博客
关于我
stl源码剖析05——set、map源码剖析
阅读量:521 次
发布时间:2019-03-08

本文共 16137 字,大约阅读时间需要 53 分钟。

一、set

  • set语法使用参阅:

set的特性

  • set所有元素都会根据元素的键值自动被排序
  • set中的键值就是实值,实值就是键值
  • 默认情况下set不允许两个元素重复

set的迭代器

  • 不能根据set的迭代器改变set元素的值。因为其键值就是实值,实值就是键值,如果改变set元素值,会严重破坏set组织
  • 在后面的源码中会看到,set的迭代器set<T>::iterator被定义为底层RB-tree的const_iterator。因此set的迭代器是一种constant iterators

set拥有与list的相同的某些性质

  • 当客户端对它进行元素新增(insert)操作或删除(erase)操作时,操作之前的所有迭代器在操作完成之后依然有效(当然,被删除的那个元素的迭代器无效)

相关算法

  • STL提供了一组set/multiset相关算法,包括交集(set_intersection)、联集(set_union)、差集(set_difference)、对称差集(set_symmetric_difference)
  • 详情会在后面的“算法”文章中介绍

set的底层结构

  • 由于RB-tree是一种平衡二叉搜索树,自动排序的效果很不错,所以标准的STL set是以RB-tree为底层机制
  • 又由于set所开放的各种操作接口,RB-tree也都提供了,所以几乎所有的set操作行为,都只是转调用RB-tree的操作行为而已
  • RB-tree参阅:

set源码

  • 下面是set的源代码摘录
//代码摘录于stl_set.htemplate 
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_compare, _Alloc> _Rep_type; _Rep_type _M_t; // 采用红黑树来表现setpublic: 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
set(_InputIterator __first, _InputIterator __last) : _M_t(_Compare(), allocator_type()) { _M_t.insert_unique(__first, __last); } template
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
insert(const value_type& __x) { pair
__p = _M_t.insert_unique(__x); return pair
(__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
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
equal_range(const key_type& __x) const { return _M_t.equal_range(__x); } #ifdef __STL_TEMPLATE_FRIENDS template
friend bool operator== (const set<_K1,_C1,_A1>&, const set<_K1,_C1,_A1>&); template
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的使用案例

#include 
#include
using namespace std; int main(){ int i; int ia[5] = { 0,1,2,3,4 }; set
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
::iterator ite1 = iset.begin(); set
::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;}

二、map

  • map语法使用参阅:

map的特性

  • 所有元素都会根据元素的键值自动被排序

map中的pair结构

  • map的所有元素类型都是pair,同时拥有实值(value)和键值(key)
  • pair的第一个元素视为键值,第二个元素视为实值
  • map不允许两个元素拥有相同的键值
  • 下面是stl_pair.h中pair的定义:
//代码摘录与stl_pair.htemplate 
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
pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {}#endif};

 

map的迭代器

  • 不可以根据map的迭代器改变节点的键值,但是可以通过map的迭代器改变节点的实值
  • 因此,map iterators既不是一种constant iterators,也不是一种mutable iterators

map拥有与list的相同的某些性质

  • 当客户端对它进行元素新增(insert)操作或删除(erase)操作时,操作之前的所有迭代器在操作完成之后依然有效(当然,被删除的那个元素的迭代器无效)

map的底层结构

  • 由于RB-tree是一种平衡二叉搜索树,自动排序的效果很不错,所以标准的STL map是以RB-tree为底层机制
  • 又由于map所开放的各种操作接口,RB-tree也都提供了,所以几乎所有的map操作行为,都只是转调用RB-tree的操作行为而已
  • RB-tree参阅:
  • 下面是map的结构:

map源码

  • 下面是map的源代码摘录
//代码摘录与stl_map.htemplate 
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
value_type; //元素类型(键值/实值) typedef _Compare key_compare; //键值比较函数 //以下定义一个functor,作用就是调用“元素比较函数” class value_compare : public binary_function
{ 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_compare, _Alloc> _Rep_type; _Rep_type _M_t; // 以红黑树实现mappublic: 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
map(_InputIterator __first, _InputIterator __last) : _M_t(_Compare(), allocator_type()) { _M_t.insert_unique(__first, __last); } template
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
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
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
equal_range(const key_type& __x) { return _M_t.equal_range(__x); } pair
equal_range(const key_type& __x) const { return _M_t.equal_range(__x); } #ifdef __STL_TEMPLATE_FRIENDS template
friend bool operator== (const map<_K1, _T1, _C1, _A1>&, const map<_K1, _T1, _C1, _A1>&); template
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函数:
    • 返回pair类型。pair参数1位返回的元素,第2个参数为bool,表示是否插入成功。插入成功的话pair参数1才保存返回的节点元素
    • 底层交给RB-tree的insert_unique去执行
pair
insert(const value_type& __x){ return _M_t.insert_unique(__x); }
  • 下标运算符([]):
    • 左值运用:内容可被修改
    • 右值运用:内容不可被修改
map
simap;simap[std::string("dongshao")] = 1; //左值运用int number = simap[std::string("dongshao")];//右值运用
  • 下标运算符的定义如下

map的使用案例

#include 
#include
#include
#include
using namespace std; int main(){ map
simap; simap[std::string("jjhou")] = 1; simap[std::string("jerry")] = 2; simap[std::string("jason")] = 3; simap[std::string("jimmy")] = 4; std::pair
value(std::string("david"), 5); simap.insert(value); map
::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
::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;}

转载地址:http://gllnz.baihongyu.com/

你可能感兴趣的文章
Mysql order by与limit混用陷阱
查看>>
Mysql order by与limit混用陷阱
查看>>
mysql order by多个字段排序
查看>>
MySQL Order By实现原理分析和Filesort优化
查看>>
mysql problems
查看>>
mysql replace first,MySQL中处理各种重复的一些方法
查看>>
MySQL replace函数替换字符串语句的用法(mysql字符串替换)
查看>>
mysql replace用法
查看>>
Mysql Row_Format 参数讲解
查看>>
mysql select, from ,join ,on ,where groupby,having ,order by limit的执行顺序和书写顺序
查看>>
MySQL Server 5.5安装记录
查看>>
mysql server has gone away
查看>>
mysql slave 停了_slave 停止。求解决方法
查看>>
MySQL SQL 优化指南:主键、ORDER BY、GROUP BY 和 UPDATE 优化详解
查看>>
MYSQL sql语句针对数据记录时间范围查询的效率对比
查看>>
mysql sum 没返回,如果没有找到任何值,我如何在MySQL中获得SUM函数以返回'0'?
查看>>
mysql Timestamp时间隔了8小时
查看>>
Mysql tinyint(1)与tinyint(4)的区别
查看>>
mysql union orderby 无效
查看>>
mysql v$session_Oracle 进程查看v$session
查看>>