STL源码剖析-map

1.容器rb_tree

Red-Black tree(红黑树)是平衡二元搜寻树(balanced binary search tree)中常被使用的一种平衡二元搜寻树的特点:排列规则有利于search和insert,并保持适度平衡-无任何节点过深

rb_tree提供遍历操作以及iterators

按正常规则(++ite)遍历,便能获得排序状态(sorted)

我们不应该使用rb_tree的iterators改变元素值(因为元素有其严谨排列规则)。编程里面(programming leve)并未阻绝此事。如此设计是正确的,因为rb_tree即将为set和map服务(做为其底部支持),而map允许元素的data被改变,只有元素的key才是不可被改变的

rb_tree提供两种insertion操作:insert_unique()和insert_equal()。前者表示节点的key一定在整个tree中独一无二,否则安插失败。后者表示节点的key可重复

 
  1. #include <set>

  2. #include <iostream>

  3. using namespace std;

  4. //容器rb_tree

  5. // key和data合成value(key|value)

  6. //template<class Key, class Value, class KeyOfValue, class Compare, class Alloc = alloc>

  7. //class rb_tree {

  8. //protected:

  9. // typedef __rb_tree_node<Value> rb_tree_node;

  10. // ...

  11. //public:

  12. // typedef rb_tree_node* link_type;

  13. //protected:

  14. // //RB-tree只以三笔表现他自己

  15. // size_type node_count; // rb_tree的大小(节点)

  16. // link_type header;

  17. // Compare key_compare; //key的大小比较规则,应会是个function object

  18. //};

  19. namespace jj31

  20. {

  21. void test_Rb_tree()

  22. {

  23. //G2.9 vs. G4.9 :

  24. //rb_tree => _Rb_tree,

  25. //identity<> => _Identity<>

  26. //insert_unique() => _M_insert_unique()

  27. //insert_equal() => _M_insert_equal()

  28. cout << "\ntest_Rb_tree().......... \n";

  29. _Rb_tree<int, int, _Identity<int>, less<int> > itree;

  30. cout << itree.empty() << endl; //1

  31. cout << itree.size() << endl; //0

  32. itree._M_insert_unique(3);

  33. itree._M_insert_unique(8);

  34. itree._M_insert_unique(5);

  35. itree._M_insert_unique(9);

  36. itree._M_insert_unique(13);

  37. itree._M_insert_unique(5); //no effect, since using insert_unique().

  38. cout << itree.empty() << endl; //0

  39. cout << itree.size() << endl; //5

  40. cout << itree.count(5) << endl; //1

  41. itree._M_insert_equal(5);

  42. itree._M_insert_equal(5);

  43. cout << itree.size() << endl; //7, since using insert_equal().

  44. cout << itree.count(5) << endl; //3

  45. }

  46. }

  47. int main() {

  48. jj31::test_Rb_tree();

  49. return 0;

  50. }

2.容器map,multimap

(1)map/multimap以rb_tree为底层结构,因此有元素自动排序特性,排序的依据是key.                           
(2)map/multimap提供"遍历"操作及iterators,按正常规则(++ite)遍历,便能获得排序状态(sorted)              
(3)我们无法使用map/multimap的iterators改变元素的key(因为key有其严谨的排列规则),但可以用它改变元素的data,
因此,map/multimap内部自动将user指定的key type设为const,如此禁止user对元素的key赋值,map不允许迭代器来改key   

(4)map元素的key必须独一无二,因此其insert()用的是rb_tree的insert_unique                               
   multimap元素的key可以重复,因此其insert()用的是rb_tree的insert_equal

 
  1. template <class _Key, class _Tp, class _Compare, class _Alloc>

  2. class map {

  3. public:

  4. // typedefs:

  5. typedef _Key key_type;

  6. typedef _Tp data_type;

  7. typedef _Tp mapped_type;

  8. typedef pair<const _Key, _Tp> value_type;

  9. // key|data,key和data合成value

  10. // map/multimap内部自动将user指定的key type设为const,如此禁止user对元素的key赋值

  11. typedef _Compare key_compare;

  12. private:

  13. typedef _Rb_tree<key_type, value_type,

  14. _Select1st<value_type>, key_compare, _Alloc> _Rep_type;

  15. _Rep_type _M_t; // red-black tree representing map

  16. public:

  17. typedef typename _Rep_type::iterator iterator;

  18. };

  19. map<int, string> imap -> map<int, string, less<int>, alloc> imap ->

  20. template<int, pair<const int, string>, select1st<pair<const int, string>>, less<int>, alloc> class rb_tree;

3.容器map,独特的operator[]

返回与下标中指定的键关联的数据                                                                      
如果key不存在,则使用默认值创建具有key的对,然后返回该值                                            
 

 
  1. _Tp& operator[](const key_type& __k) {                                                              

  2.     iterator __i = lower_bound(__k);                                                                

  3.     // __i->first is greater than or equivalent to __k.                                             

  4.     if (__i == end() || key_comp()(__k, (*__i).first))                                              

  5.         __i = insert(__i, value_type(__k, _Tp()));                                                  

  6.     return (*__i).second;                                                                           

lower_bound是二分搜寻的一种版本,试图在sorted[first, last)中寻找元素value                            
若[first, last)拥有value相等的元素(s),便返回一个iterator指向其中第一个元素                          
如果没有这样的元素存在,便返回假设该元素存在时应该出现的位置                                         
lower_bound返回的是 不破坏排序得以安插value的第一个适当位置   

 
  1. #include <map>

  2. #include <stdexcept>

  3. #include <string>

  4. #include <cstdlib> //abort() and rand() and RAND_MAX

  5. #include <cstdio> //snprintf()

  6. #include <iostream>

  7. #include <ctime>

  8. using namespace std;

  9. namespace jj14

  10. {

  11. long get_a_target_long()

  12. {

  13. long target=0;

  14. cout << "target (0~" << RAND_MAX << "): ";

  15. cin >> target;

  16. return target;

  17. }

  18. void test_map(long& value)

  19. {

  20. cout << "\ntest_map().......... \n";

  21. map<long, string> c;

  22. char buf[10];

  23. clock_t timeStart = clock();

  24. for(long i=0; i< value; ++i)

  25. {

  26. try {

  27. snprintf(buf, 10, "%d", rand());

  28. c[i] = string(buf);

  29. }

  30. catch(exception& p) {

  31. cout << "i=" << i << " " << p.what() << endl;

  32. abort();

  33. }

  34. }

  35. cout << "milli-seconds : " << (clock()-timeStart) << endl;

  36. cout << "map.size()= " << c.size() << endl;

  37. cout << "map.max_size()= " << c.max_size() << endl; //178956970

  38. long target = get_a_target_long();

  39. timeStart = clock();

  40. auto pItem = c.find(target);

  41. cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;

  42. if (pItem != c.end())

  43. cout << "found, value=" << (*pItem).second << endl;

  44. else

  45. cout << "not found! " << endl;

  46. c.clear();

  47. }

  48. }

  49. int main() {

  50. long value;

  51. cout << "how many elements: ";

  52. cin >> value;

  53. jj14::test_map(value);

  54. }

4.map容器迭代器失效问题

迭代器失效_INGNIGHT的博客-CSDN博客

 
  1. #include <iostream>

  2. #include <map>

  3. using namespace std;

  4. class Key {

  5. public:

  6. explicit Key(int num):_num(num) {

  7. }

  8. int get_num() const {

  9. return _num;

  10. }

  11. bool operator < (const Key& k) const {

  12. return get_num() < k.get_num() ? true : false;

  13. }

  14. public:

  15. int _num;

  16. };

  17. class CompareKey : public binary_function<Key, Key, bool> {

  18. public:

  19. bool operator()(const Key& k1, const Key& k2) {

  20. return k1.get_num() < k2.get_num() ? true : false;

  21. }

  22. };

  23. int main() {

  24. //std::map<Key, int, CompareKey> table;

  25. std::map<Key, int> table;

  26. table.insert(std::pair<Key, int>(Key(0), 1));

  27. table.insert(std::pair<Key, int>(Key(1), 1));

  28. table.insert(std::pair<Key, int>(Key(3), 1));

  29. table.insert(std::pair<Key, int>(Key(4), 1));

  30. table.insert(std::pair<Key, int>(Key(5), 1));

  31. cout << table.begin()->first.get_num() << std::endl;

  32. cout << table.rbegin()->first.get_num() << std::endl;

  33. auto ite = table.lower_bound(Key(1));

  34. cout << ite->first.get_num() << std::endl;;

  35. ite = table.lower_bound(Key(2));

  36. cout << ite->first.get_num() << std::endl;;

  37. ite = table.upper_bound(Key(2));

  38. cout << ite->first.get_num() << std::endl;;

  39. ite = table.upper_bound(Key(1));

  40. cout << ite->first.get_num() << std::endl;;

  41. }

STL源码剖析-map_stl map源码、-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值