• C++ -- 学习系列 关联式容器 set 与 map


    一   关联式容器是什么?

    c++ 中有两种容器类型:关联式容器与序列式容器(顺序容器)

    关联式中的容器是按照关键字来存储与访问的,序列式容器(顺序容器)则是元素在容器中的相对位置来存储与访问的。

    c++ 中的关联式容器主要是 set 与 map.

    二   底层原理与源码

    1. 红黑树

           红黑树是一种平衡二叉搜索树(balanced binary search tree),即插入或者删除元素后,依然能够保证树是平衡的,所谓平衡意味着任意一个父节点,其左右子树的深度相差不会太多。

    平衡树也称 AVL 树,任意节点的左右个子树的高度差不超过1。

    这一特性也保证了在插入元素与查找元素时的效率。

    红黑树核心法则:

    1. 每个节点要么是红色,要么是黑色

    2. 红黑树中的任意节点到达其每个叶子节点的黑色高度是相同的(黑色高度值得是某个节点到达叶子节点的黑色节点的个数,因叶子节点是黑色的,所以也包括叶子节点)

    3. 两个红色节点之间不能相邻,即对于任意一个红色节点而言,其左右子节点定不是红色

    4. 根节点必须是黑色的

    5. 每个红色节点的两个子节点一定是黑色的

    【红黑树】的详细实现(C++)附代码 - 知乎 (zhihu.com)

    c++ 中的红黑树源代码位置

    #include  
    
    1. template<typename _Key, typename _Val, typename _KeyOfValue,
    2. typename _Compare, typename _Alloc = allocator<_Val> >
    3. class _Rb_tree
    4. {
    5. typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
    6. rebind<_Rb_tree_node<_Val> >::other _Node_allocator;
    7. typedef __gnu_cxx::__alloc_traits<_Node_allocator> _Alloc_traits;
    8. protected:
    9. typedef _Rb_tree_node_base* _Base_ptr;
    10. typedef const _Rb_tree_node_base* _Const_Base_ptr;
    11. typedef _Rb_tree_node<_Val>* _Link_type;
    12. typedef const _Rb_tree_node<_Val>* _Const_Link_type;
    13. ......
    14. };

    源码中的模板参数解释如下:

    1. Key 为存储在红黑树中的关键字类型

    2. Value 实际存储数据的类型

    3. KeyOfValue 表示如何通过 Value 获取到 Key,通常是一个函数

    4. Compare 则为比较元素大小的函数,可自定义实现

    5. Alloc 分配内存的方式

    1. #include
    2. #include
    3. int main()
    4. {
    5. // template
    6. // struct _Identity
    7. // : public unary_function<_Tp,_Tp>
    8. // {
    9. // _Tp&
    10. // operator()(_Tp& __x) const
    11. // { return __x; }
    12. // const _Tp&
    13. // operator()(const _Tp& __x) const
    14. // { return __x; }
    15. // };
    16. std::_Rb_tree<int, int, std::_Identity<int>, std::less<int>> rb_tree;
    17. std::cout << rb_tree.empty() << std::endl;
    18. std::cout << rb_tree.size() << std::endl;
    19. // 1. 插入元素不允许重复.
    20. rb_tree._M_insert_unique(1);
    21. rb_tree._M_insert_unique(2);
    22. rb_tree._M_insert_unique(3);
    23. rb_tree._M_insert_unique(4);
    24. rb_tree._M_insert_unique(5);
    25. std::cout << rb_tree.size() << std::endl;
    26. rb_tree._M_insert_unique(1);
    27. std::cout << rb_tree.size() << std::endl;
    28. std::cout << "------" << std::endl;
    29. // 2. 插入元素允许重复.
    30. rb_tree._M_insert_equal(1);
    31. rb_tree._M_insert_equal(1);
    32. rb_tree._M_insert_equal(1);
    33. std::cout << rb_tree.size() << std::endl;
    34. for(auto iter = rb_tree.begin(); iter != rb_tree.end(); iter++)
    35. {
    36. std::cout << *iter <<" ";
    37. }
    38. std::cout <<""<
    39. return 0;
    40. }

    2. 基于红黑树的关联式容器

    2.1 set/multiset

    set/multiset 是以红黑树为底层结构的,因此存入的元素具有自动排序的特性,排序的依据是 key ,而 set/miltiset  元素的 key 与 value是合二为一的,其value 就是 key;

    set/multiset  提供遍历操作与迭代器 iterator, 通过 不断的 iterator++ 遍历可以获取到已经排好序的元素;

    我们无法通过 迭代器来改变 set/multiset 的值,这样设计的原因是 若是可以随意修改值,那么按照key 排好的顺序便有可能不存在了,从代码上来讲,set/multiset 用的迭代器是底层红黑树类 _Rb_tree 的 const iterator ,禁止使用者赋值。

     2.1.1 set 源代码
    1. template<typename _Key, typename _Compare = std::less<_Key>,
    2. typename _Alloc = std::allocator<_Key> >
    3. class set
    4. {
    5. public:
    6. // typedefs:
    7. //@{
    8. /// Public typedefs.
    9. typedef _Key key_type;
    10. typedef _Key value_type;
    11. typedef _Compare key_compare;
    12. typedef _Compare value_compare;
    13. typedef _Alloc allocator_type;
    14. private:
    15. typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
    16. rebind<_Key>::other _Key_alloc_type;
    17. typedef _Rb_tree,
    18. key_compare, _Key_alloc_type> _Rep_type;
    19. _Rep_type _M_t; // Red-black tree representing set.
    20. typedef __gnu_cxx::__alloc_traits<_Key_alloc_type> _Alloc_traits;
    21. .....
    22. iterator
    23. insert(const_iterator __position, const value_type& __x)
    24. { return _M_t._M_insert_unique_(__position, __x); }
    25. .....
    26. };

    通过源码可以看出,set 底层使用的是 _Rb_tree , insert 函数底层调用的是 _Rb_tree 的 insert_unique 函数,即 _Rb_tree 中的元素不重复。

    2.1.2 multiset 源码
    1. template <typename _Key, typename _Compare = std::less<_Key>,
    2. typename _Alloc = std::allocator<_Key> >
    3. class multiset
    4. {
    5. #ifdef _GLIBCXX_CONCEPT_CHECKS
    6. // concept requirements
    7. typedef typename _Alloc::value_type _Alloc_value_type;
    8. # if __cplusplus < 201103L
    9. __glibcxx_class_requires(_Key, _SGIAssignableConcept)
    10. # endif
    11. __glibcxx_class_requires4(_Compare, bool, _Key, _Key,
    12. _BinaryFunctionConcept)
    13. __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept)
    14. #endif
    15. public:
    16. // typedefs:
    17. typedef _Key key_type;
    18. typedef _Key value_type;
    19. typedef _Compare key_compare;
    20. typedef _Compare value_compare;
    21. typedef _Alloc allocator_type;
    22. private:
    23. /// This turns a red-black tree into a [multi]set.
    24. typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
    25. rebind<_Key>::other _Key_alloc_type;
    26. typedef _Rb_tree,
    27. key_compare, _Key_alloc_type> _Rep_type;
    28. /// The actual tree structure.
    29. _Rep_type _M_t;
    30. typedef __gnu_cxx::__alloc_traits<_Key_alloc_type> _Alloc_traits;
    31. ......
    32. iterator
    33. insert(const value_type& __x)
    34. { return _M_t._M_insert_equal(__x); }
    35. ......
    36. };

    通过源码可以看出,multiset 底层使用的是 _Rb_tree , insert 函数底层调用的是 _Rb_tree 的 insert_equal 函数,即 _Rb_tree 中的元素允许重复。

    2.2 map/multimap

    map/multimap 是以红黑树为底层结构的,因此存入的元素具有自动排序的特性,排序的依据是 key;

    map/multimap 提供遍历操作与迭代器 iterator, 通过 不断的 iterator++ 遍历可以获取到已经按照 key 排好序的元素;

    我们无法通过 迭代器来改变 map/multimap 的值,这样设计的原因是 若是可以随意修改值,那么按照 key 排好的顺序便有可能不存在了,但是我们可以修改 key 对应的 data 值。因而 map/multimap 内部将 key type 设为 const ,如此可以避免对 key 的随意修改。

    map 的key 是独一无二的,所以底层使用 _Rb_tree 的 insert_unique 函数;

    multimap 的key允许重复,所以底层使用 _Rb_tree 的 insert_equal 函数

    2.2.1  map 源码
    1. template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
    2. typename _Alloc = std::allocatorconst _Key, _Tp> > >
    3. class map
    4. {
    5. public:
    6. typedef _Key key_type;
    7. typedef _Tp mapped_type;
    8. typedef std::pair<const _Key, _Tp> value_type;
    9. typedef _Compare key_compare;
    10. typedef _Alloc allocator_type;
    11. private:
    12. /// This turns a red-black tree into a [multi]map.
    13. typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
    14. rebind::other _Pair_alloc_type;
    15. typedef _Rb_tree,
    16. key_compare, _Pair_alloc_type> _Rep_type;
    17. /// The actual tree structure.
    18. _Rep_type _M_t;
    19. typedef __gnu_cxx::__alloc_traits<_Pair_alloc_type> _Alloc_traits;
    20. .....
    21. std::pairbool>
    22. insert(const value_type& __x)
    23. { return _M_t._M_insert_unique(__x); }
    24. .....
    25. };

    通过源码可以看到 map 的 insert 函数底层调用的是 insert_unique 函数,所以 map 的 key 是唯一的。

    2.2.2 multimap 源码
    1. template <typename _Key, typename _Tp,
    2. typename _Compare = std::less<_Key>,
    3. typename _Alloc = std::allocatorconst _Key, _Tp> > >
    4. class multimap
    5. {
    6. public:
    7. typedef _Key key_type;
    8. typedef _Tp mapped_type;
    9. typedef std::pair<const _Key, _Tp> value_type;
    10. typedef _Compare key_compare;
    11. typedef _Alloc allocator_type;
    12. private:
    13. /// This turns a red-black tree into a [multi]map.
    14. typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
    15. rebind::other _Pair_alloc_type;
    16. typedef _Rb_tree,
    17. key_compare, _Pair_alloc_type> _Rep_type;
    18. /// The actual tree structure.
    19. _Rep_type _M_t;
    20. typedef __gnu_cxx::__alloc_traits<_Pair_alloc_type> _Alloc_traits;
    21. ......
    22. iterator
    23. insert(const value_type& __x)
    24. { return _M_t._M_insert_equal(__x); }
    25. ......
    26. };

    通过源码可以看到 multimap 的 insert 函数底层调用的是 insert_equal 函数,所以 map 的 key 是可以重复的。

    2.2.3  Select1st

    前面的源码中提到了  Select1st,该函数的作用是获取 pair 中的第一个元素,应用在 map 中,获取的就是 key

    Select1st 源码如下:

    1. template<typename _Pair>
    2. struct _Select1st
    3. : public unary_function<_Pair, typename _Pair::first_type>
    4. {
    5. typename _Pair::first_type&
    6. operator()(_Pair& __x) const
    7. { return __x.first; }
    8. const typename _Pair::first_type&
    9. operator()(const _Pair& __x) const
    10. { return __x.first; }
    11. };

    三  使用

    1. set/multiset

      1.1 set 函数

    std::set - cppreference.com       

       1.1.1  构造函数
    函数说明
    set()空构造函数
     template	set(_InputIterator __first, _InputIterator __last)
    range 构造函数
        1.1.2  容器修改
    函数说明
    clear()清空容器
    insert插入元素
    emplace插入元素,可以只传入元素类的构造函数所需参数
    erase移除指定位置的元素
        1.1.3  容器查找
    函数说明
    count返回指定元素的个数
    begin()返回首元素的 iterator
    end()返回尾元素下一地址的 iterator,该 iterator 不能获取元素
    find查找指定元素,若是存在返回指向该元素的 iterator;若是不存在,则返回尾 iterator
    lower_boundIterator pointing to the first element that is not less than key. If no such element is found, a past-the-end iterator (see end()) is returned.
    uppser_bound

    Iterator pointing to the first element that is greater than key. If no such element is found, past-the-end (see end()) iterator is returned.

    1.1.4  容器容量
    函数说明
    empty()判断 set 是否为空
    size()返回 set 中的元素个数
    1.1.5  示例
    1. #include
    2. #include
    3. int main()
    4. {
    5. // 1. 构造函数
    6. std::set<int> unique_set1;
    7. int nums[] = {1, 2, 3, 4, 5, 6};
    8. std::set<int> unique_set2(nums, nums+6);
    9. std::set<int> unique_set3(unique_set2.begin(), unique_set2.end());
    10. // 2. 容器修改
    11. unique_set1.insert(1);
    12. unique_set1.insert(2);
    13. unique_set1.insert(3);
    14. unique_set1.emplace(4);
    15. unique_set1.emplace(5);
    16. unique_set1.erase(4);
    17. // 3. 容器查找
    18. std::cout << unique_set1.count(3) << std::endl; // 1
    19. auto item1_iter = unique_set1.find(3);
    20. std::cout << (item1_iter == unique_set1.end()) << ", " << *item1_iter << std::endl; // 0 , 3
    21. auto item2_iter = unique_set1.lower_bound(4);
    22. std::cout << (item2_iter == unique_set1.end()) << ", " << *item2_iter << std::endl; // 0 , 3
    23. auto item3_iter = unique_set1.upper_bound(5);
    24. std::cout << (item3_iter == unique_set1.end()) << ", " << *item3_iter << std::endl;
    25. // 0 , 5
    26. for(auto iter = unique_set1.begin(); iter != unique_set1.end(); iter++)
    27. {
    28. std::cout << *iter << " "; // 1. 2, 3, 5
    29. }
    30. std::cout << "" << std::endl;
    31. // 4. 容器容量
    32. std::cout << unique_set1.size() << std::endl; // 4
    33. std::cout << unique_set1.empty() << std::endl; // 0
    34. unique_set1.clear();
    35. std::cout << unique_set1.size() << std::endl; // 0
    36. std::cout << unique_set1.empty() << std::endl; // 1
    37. return 0;
    38. }

     1.2 multiset 函数

        std::multiset - cppreference.com

     1.2.1  构造函数
    函数说明
    set()空构造函数
     template	set(_InputIterator __first, _InputIterator __last)
    range 构造函数
        1.2.2  容器修改
    函数说明
    clear()清空容器
    insert插入元素
    emplace插入元素,可以只传入元素类的构造函数所需参数
    erase移除指定位置的元素
        1.2.3  容器查找
    函数说明
    count返回指定元素的个数
    begin()返回首元素的 iterator
    end()返回尾元素下一地址的 iterator,该 iterator 不能获取元素
    find查找指定元素,若是存在返回指向该元素的 iterator;若是不存在,则返回尾 iterator
    lower_boundIterator pointing to the first element that is not less than key. If no such element is found, a past-the-end iterator (see end()) is returned.
    uppser_bound

    Iterator pointing to the first element that is greater than key. If no such element is found, past-the-end (see end()) iterator is returned.

    1.2.4  容器容量
    函数说明
    empty()判断 set 是否为空
    size()返回 set 中的元素个数
    1.2.5  示例
    1. #include
    2. #include
    3. int main()
    4. {
    5. // 1. 构造函数
    6. std::multiset<int> multi_set1;
    7. int nums1[] = {1, 2, 3, 4, 5, 6};
    8. std::multiset<int> multi_set2(nums1, nums1+6);
    9. std::multiset<int> multi_set3(multi_set2.begin(), multi_set2.end());
    10. // 2. 容器修改
    11. multi_set1.insert(1);
    12. multi_set1.insert(2);
    13. multi_set1.insert(3);
    14. multi_set1.insert(3);
    15. multi_set1.insert(3);
    16. multi_set1.emplace(4);
    17. multi_set1.emplace(5);
    18. multi_set1.erase(4);
    19. // 3. 容器查找
    20. std::cout << multi_set1.count(3) << std::endl; // 3
    21. auto item1_iter = multi_set1.find(3);
    22. std::cout << (item1_iter == multi_set1.end()) << ", " << *item1_iter << std::endl; // 0, 3
    23. auto item2_iter = multi_set1.lower_bound(4);
    24. std::cout << (item2_iter == multi_set1.end()) << ", " << *item2_iter << std::endl; // 0, 5
    25. auto item3_iter = multi_set1.upper_bound(4);
    26. std::cout << (item3_iter == multi_set1.end()) << ", " << *item3_iter << std::endl; // 0, 5
    27. for(auto iter = multi_set1.begin(); iter != multi_set1.end(); iter++)
    28. {
    29. std::cout << *iter << " "; // 1 2 3 3 3 5
    30. }
    31. std::cout << "" << std::endl;
    32. // 4. 容器容量
    33. std::cout << multi_set1.size() << std::endl; // 6
    34. std::cout << multi_set1.empty() << std::endl; // 0
    35. multi_set1.clear();
    36. std::cout << multi_set1.size() << std::endl; // 0
    37. std::cout << multi_set1.empty() << std::endl; // 1
    38. return 0;
    39. }

    2. map/multimap

    2.1 map 函数

            2.1.1  构造函数
    函数说明
    map默认构造函数
    template< class InputIt >

    map( InputIt first, InputIt last)

    range 构造函数
    map( std::initializer_list init)initializer list 构造函数
            2.1.2  容器修改
    函数说明
    clear()清空容器
    insert插入元素
    emplace插入元素,可以只传入元素类的构造函数所需参数
    erase移除指定位置的元素
            2.1.3  容器访问
    函数说明
    count返回指定 key 元素的个数
    begin()返回首元素的 iterator
    end()返回尾元素下一地址的 iterator,该 iterator 不能获取元素
    find查找指定元素,若是存在返回指向该元素的 iterator;若是不存在,则返回尾 iterator
    lower_boundIterator pointing to the first element that is not less than key. If no such element is found, a past-the-end iterator (see end()) is returned.
    uppser_bound

    Iterator pointing to the first element that is greater than key. If no such element is found, past-the-end (see end()) iterator is returned.

    atReturns a reference to the mapped value of the element with key equivalent to key. If no such element exists, an exception of type std::out_of_range is thrown.
    operator[]Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
            2.1.4  容器容量
    函数说明
    empty()判断 set 是否为空
    size()返回 set 中的元素个数
            2.1.5  示例
    1. #include
    2. #include
    3. int main()
    4. {
    5. // 1. 构造函数
    6. std::map<int, std::string> unique_map1;
    7. std::map<int, std::string> unique_map2 = {{1, "a"}, {22, "bb"}, {3, "c"}};
    8. std::map<int, std::string> unique_map3(unique_map2.begin(), unique_map2.end());
    9. // 2. 容器修改
    10. unique_map1.insert({5, "e"});
    11. unique_map1.insert({6, "f"});
    12. unique_map1.emplace(7, "g");
    13. unique_map1.emplace(8, "h");
    14. unique_map1.insert({16, "ff"});
    15. unique_map1.erase(16);
    16. // 3. 容器访问
    17. std::cout << unique_map1.count(6) << std::endl; // 1
    18. auto item_iter1 = unique_map1.find(6);
    19. std::cout << (item_iter1 == unique_map1.end()) << std::endl; // 0
    20. std::cout << item_iter1->first << ", " << item_iter1->second << std::endl; // 6, f
    21. auto item_iter2 = unique_map1.lower_bound(6);
    22. std::cout << item_iter2->first << ", " << item_iter2->second << std::endl; // 6, f
    23. auto item_iter3 = unique_map1.upper_bound(7);
    24. std::cout << item_iter3->first << ", " << item_iter3->second << std::endl; // 8, h
    25. std::cout << unique_map1.at(7) << std::endl; // g
    26. std::cout << unique_map1[7] << std::endl; // g
    27. // 4. 容器容量
    28. std::cout << unique_map1.empty() << std::endl; // 0
    29. std::cout << unique_map1.size() << std::endl; // 4
    30. unique_map1.clear();
    31. std::cout << unique_map1.empty() << std::endl; // 1
    32. std::cout << unique_map1.size() << std::endl; // 0
    33. return 0;
    34. }

     2.2 multimap 函数

             2.1.1  构造函数
    函数说明
    map默认构造函数
    template< class InputIt >

    map( InputIt first, InputIt last)

    range 构造函数
    map( std::initializer_list init)initializer list 构造函数
              2.1.2  容器修改
    函数说明
    clear()清空容器
    insert插入元素
    emplace插入元素,可以只传入元素类的构造函数所需参数
    erase移除指定位置的元素
            2.1.3  容器访问
    函数说明
    count返回指定 key 元素的个数
    begin()返回首元素的 iterator
    end()返回尾元素下一地址的 iterator,该 iterator 不能获取元素
    find查找指定元素,若是存在返回指向该元素的 iterator;若是不存在,则返回尾 iterator
    lower_boundIterator pointing to the first element that is not less than key. If no such element is found, a past-the-end iterator (see end()) is returned.
    uppser_bound

    Iterator pointing to the first element that is greater than key. If no such element is found, past-the-end (see end()) iterator is returned.

            2.1.4  容器容量
    函数说明
    empty()判断 set 是否为空
    size()返回 set 中的元素个数
            2.1.5  示例
    1. #include
    2. #include
    3. int main()
    4. {
    5. // 1. 构造函数
    6. std::multimap<int, std::string> multi_map1;
    7. std::multimap<int, std::string> multi_map2 = {{1, "a"}, {22, "bb"}, {3, "c"}};
    8. std::multimap<int, std::string> multi_map3(multi_map2.begin(), multi_map2.end());
    9. // 2. 容器修改
    10. multi_map1.insert({5, "e"});
    11. multi_map1.insert({6, "f"});
    12. multi_map1.emplace(7, "g1");
    13. multi_map1.emplace(7, "g2");
    14. multi_map1.emplace(7, "g3");
    15. multi_map1.emplace(8, "h");
    16. multi_map1.insert({16, "ff"});
    17. multi_map1.erase(16);
    18. // 3. 容器访问
    19. std::cout << multi_map1.count(6) << std::endl; // 1
    20. auto item_iter1 = multi_map1.find(6);
    21. std::cout << (item_iter1 == multi_map1.end()) << std::endl; // 0
    22. std::cout << item_iter1->first << ", " << item_iter1->second << std::endl; // 6, f
    23. auto item_iter2 = multi_map1.lower_bound(6);
    24. std::cout << item_iter2->first << ", " << item_iter2->second << std::endl; // 6, f
    25. auto item_iter3 = multi_map1.upper_bound(7);
    26. std::cout << item_iter3->first << ", " << item_iter3->second << std::endl; // 8, h
    27. // 4. 容器容量
    28. std::cout << multi_map1.empty() << std::endl; // 0
    29. std::cout << multi_map1.size() << std::endl; // 6
    30. multi_map1.clear();
    31. std::cout << multi_map1.empty() << std::endl; // 1
    32. std::cout << multi_map1.size() << std::endl; // 0
    33. return 0;
    34. }

    四  简单实现

          1. my_set

    1. // my_set.h
    2. #include
    3. template<typename T>
    4. class my_set
    5. {
    6. typedef T ValueType;
    7. typedef T KeyType;
    8. typedef std::_Rb_tree, std::less> Rb_type;
    9. typedef typename std::_Rb_tree, std::less>::const_iterator const_Iterator;
    10. public:
    11. my_set()
    12. {
    13. }
    14. template<typename InputIterator>
    15. my_set(InputIterator first, InputIterator last)
    16. {
    17. rb_tree._M_insert_unique(first, last);
    18. }
    19. ~my_set()
    20. {
    21. }
    22. const_Iterator begin()
    23. {
    24. return rb_tree.begin();
    25. }
    26. const_Iterator end()
    27. {
    28. return rb_tree.end();
    29. }
    30. void clear()
    31. {
    32. rb_tree.clear();
    33. }
    34. void insert(ValueType& val)
    35. {
    36. rb_tree._M_insert_unique(val);
    37. }
    38. void insert(ValueType&& val)
    39. {
    40. rb_tree._M_insert_unique(val);
    41. }
    42. template<typename ... Args>
    43. void emplace(Args&& ... args)
    44. {
    45. rb_tree._M_emplace_unique(std::forward(args)...);
    46. }
    47. template<typename ... Args>
    48. void emplace(Args& ... args)
    49. {
    50. rb_tree._M_emplace_unique(std::forward(args)...);
    51. }
    52. void erase(ValueType& val)
    53. {
    54. rb_tree.erase(val);
    55. }
    56. void erase(ValueType&& val)
    57. {
    58. rb_tree.erase(val);
    59. }
    60. std::size_t count(ValueType& val)
    61. {
    62. return rb_tree.count(val);
    63. }
    64. std::size_t count(ValueType&& val)
    65. {
    66. return rb_tree.count(val);
    67. }
    68. const_Iterator find(ValueType& val)
    69. {
    70. return rb_tree.find(val);
    71. }
    72. const_Iterator find(ValueType&& val)
    73. {
    74. return rb_tree.find(val);
    75. }
    76. bool empty()
    77. {
    78. return rb_tree.empty();
    79. }
    80. std::size_t size()
    81. {
    82. return rb_tree.size();
    83. }
    84. private:
    85. Rb_type rb_tree;
    86. };
    87. // main.cpp
    88. int main()
    89. {
    90. // 1. 构造函数
    91. my_set<int> unique_set1;
    92. int nums[] = {1, 2, 3, 4, 5, 6};
    93. my_set<int> unique_set2(nums, nums+6);
    94. my_set<int> unique_set3(unique_set2.begin(), unique_set2.end());
    95. // 2. 容器修改
    96. unique_set1.insert(1);
    97. unique_set1.insert(2);
    98. unique_set1.insert(3);
    99. unique_set1.emplace(4);
    100. unique_set1.emplace(5);
    101. unique_set1.erase(4);
    102. // 3. 容器查找
    103. std::cout << unique_set1.count(3) << std::endl; // 1
    104. auto item1_iter = unique_set1.find(3);
    105. std::cout << (item1_iter == unique_set1.end()) << ", " << *item1_iter << std::endl; // 0. 3
    106. for(auto iter = unique_set1.begin(); iter != unique_set1.end(); iter++)
    107. {
    108. std::cout << *iter << " "; // 1 2 3 5
    109. }
    110. std::cout << "" << std::endl;
    111. // 4. 容器容量
    112. std::cout << unique_set1.size() << std::endl; // 4
    113. std::cout << unique_set1.empty() << std::endl; // 0
    114. unique_set1.clear();
    115. std::cout << unique_set1.size() << std::endl; // 0
    116. std::cout << unique_set1.empty() << std::endl; // 1
    117. return 0;
    118. }

          2. my_multiset

    1. // my_multiset.h
    2. #include
    3. template<typename T>
    4. class my_multiset
    5. {
    6. typedef T ValueType;
    7. typedef T KeyType;
    8. typedef std::_Rb_tree, std::less> Rb_type;
    9. typedef typename std::_Rb_tree, std::less>::const_iterator const_Iterator;
    10. public:
    11. my_multiset()
    12. {
    13. }
    14. template<typename InputIterator>
    15. my_multiset(InputIterator first, InputIterator last)
    16. {
    17. rb_tree._M_insert_equal(first, last);
    18. }
    19. ~my_multiset()
    20. {
    21. }
    22. const_Iterator begin()
    23. {
    24. return rb_tree.begin();
    25. }
    26. const_Iterator end()
    27. {
    28. return rb_tree.end();
    29. }
    30. void clear()
    31. {
    32. rb_tree.clear();
    33. }
    34. void insert(ValueType& val)
    35. {
    36. rb_tree._M_insert_equal(val);
    37. }
    38. void insert(ValueType&& val)
    39. {
    40. rb_tree._M_insert_equal(val);
    41. }
    42. template<typename ... Args>
    43. void emplace(Args&& ... args)
    44. {
    45. rb_tree._M_emplace_unique(std::forward(args)...);
    46. }
    47. template<typename ... Args>
    48. void emplace(Args& ... args)
    49. {
    50. rb_tree._M_emplace_unique(std::forward(args)...);
    51. }
    52. void erase(ValueType& val)
    53. {
    54. rb_tree.erase(val);
    55. }
    56. void erase(ValueType&& val)
    57. {
    58. rb_tree.erase(val);
    59. }
    60. std::size_t count(ValueType& val)
    61. {
    62. return rb_tree.count(val);
    63. }
    64. std::size_t count(ValueType&& val)
    65. {
    66. return rb_tree.count(val);
    67. }
    68. const_Iterator find(ValueType& val)
    69. {
    70. return rb_tree.find(val);
    71. }
    72. const_Iterator find(ValueType&& val)
    73. {
    74. return rb_tree.find(val);
    75. }
    76. bool empty()
    77. {
    78. return rb_tree.empty();
    79. }
    80. std::size_t size()
    81. {
    82. return rb_tree.size();
    83. }
    84. private:
    85. Rb_type rb_tree;
    86. };
    87. // main.cpp
    88. #include
    89. #include"my_multiset.h"
    90. int main()
    91. {
    92. // 1. 构造函数
    93. my_multiset<int> multi_set1;
    94. int nums[] = {1, 2, 3, 4, 5, 6};
    95. my_multiset<int> multi_set2(nums, nums+6);
    96. my_multiset<int> multi_set3(multi_set2.begin(), multi_set2.end());
    97. // 2. 容器修改
    98. multi_set1.insert(1);
    99. multi_set1.insert(2);
    100. multi_set1.insert(3);
    101. multi_set1.insert(3);
    102. multi_set1.insert(3);
    103. multi_set1.emplace(4);
    104. multi_set1.emplace(5);
    105. multi_set1.erase(4);
    106. // 3. 容器查找
    107. std::cout << multi_set1.count(3) << std::endl; // 1
    108. auto item1_iter = multi_set1.find(3);
    109. std::cout << (item1_iter == multi_set1.end()) << ", " << *item1_iter << std::endl; // 0, 3
    110. for(auto iter = multi_set1.begin(); iter != multi_set1.end(); iter++)
    111. {
    112. std::cout << *iter << " "; // 1 2 3 3 3 5
    113. }
    114. std::cout << "" << std::endl;
    115. // 4. 容器容量
    116. std::cout << multi_set1.size() << std::endl; // 6
    117. std::cout << multi_set1.empty() << std::endl; // 0
    118. multi_set1.clear();
    119. std::cout << multi_set1.size() << std::endl; // 0
    120. std::cout << multi_set1.empty() << std::endl; // 1
    121. return 0;
    122. }

         3. my_map

           

    1. // my_map.h
    2. #include
    3. #include
    4. template<typename Key, typename Value>
    5. class my_map
    6. {
    7. typedef std::pair ValueType;
    8. typedef std::_Rb_tree, std::less> Rb_type;
    9. typedef typename Rb_type::iterator Iterator;
    10. public:
    11. my_map()
    12. {
    13. }
    14. template<typename InputIterator>
    15. my_map(InputIterator first, InputIterator last)
    16. {
    17. rb_tree._M_insert_unique(first, last);
    18. }
    19. my_map(std::initializer_list init_list)
    20. {
    21. rb_tree._M_insert_unique(init_list.begin(), init_list.end());
    22. }
    23. ~my_map()
    24. {
    25. }
    26. Iterator begin()
    27. {
    28. return rb_tree.begin();
    29. }
    30. Iterator end()
    31. {
    32. return rb_tree.end();
    33. }
    34. void clear()
    35. {
    36. rb_tree.clear();
    37. }
    38. void insert(ValueType& val)
    39. {
    40. rb_tree._M_insert_unique(val);
    41. }
    42. void insert(ValueType&& val)
    43. {
    44. rb_tree._M_insert_unique(val);
    45. }
    46. template<typename ... Args>
    47. void emplace(Args&& ... args)
    48. {
    49. rb_tree._M_emplace_unique(std::forward(args)...);
    50. }
    51. void erase(Iterator iter)
    52. {
    53. rb_tree.erase(iter);
    54. }
    55. std::size_t count(Key& key)
    56. {
    57. return rb_tree.count(key);
    58. }
    59. std::size_t count(Key&& key)
    60. {
    61. return rb_tree.count(key);
    62. }
    63. Iterator find(Key& key)
    64. {
    65. return rb_tree.find(key);
    66. }
    67. Iterator find(Key&& key)
    68. {
    69. return rb_tree.find(key);
    70. }
    71. Value& at(Key& key)
    72. {
    73. return (*rb_tree.lower_bound(key)).second;
    74. }
    75. Value& at(Key&& key)
    76. {
    77. return (*rb_tree.lower_bound(key)).second;
    78. }
    79. Value& operator[](Key& key)
    80. {
    81. return (*rb_tree.lower_bound(key)).second;
    82. }
    83. Value& operator[](Key&& key)
    84. {
    85. return (*rb_tree.lower_bound(key)).second;
    86. }
    87. bool empty()
    88. {
    89. return rb_tree.empty();
    90. }
    91. std::size_t size()
    92. {
    93. return rb_tree.size();
    94. }
    95. void erase(Key& key)
    96. {
    97. rb_tree.erase(key);
    98. }
    99. void erase(Key&& key)
    100. {
    101. rb_tree.erase(key);
    102. }
    103. private:
    104. Rb_type rb_tree;
    105. };
    106. // main.cpp
    107. int main()
    108. {
    109. // 1. 构造函数
    110. my_map<int, std::string> unique_map1;
    111. my_map<int, std::string> unique_map2 = {{1, "a"}, {22, "bb"}, {3, "c"}};
    112. my_map<int, std::string> unique_map3(unique_map2.begin(), unique_map2.end());
    113. // 2. 容器修改
    114. unique_map1.insert({5, "e"});
    115. unique_map1.insert({6, "f"});
    116. unique_map1.emplace(7, "g");
    117. unique_map1.emplace(8, "h");
    118. unique_map1.insert({16, "ff"});
    119. unique_map1.erase(16);
    120. // 3. 容器访问
    121. std::cout << unique_map1.count(6) << std::endl; // 1
    122. auto item_iter1 = unique_map1.find(6);
    123. std::cout << (item_iter1 == unique_map1.end()) << std::endl; // 0
    124. std::cout << item_iter1->first << ", " << item_iter1->second << std::endl; // 6, f
    125. std::cout << unique_map1.at(7) << std::endl; // g
    126. std::cout << unique_map1[7] << std::endl; // g
    127. // 4. 容器容量
    128. std::cout << unique_map1.empty() << std::endl; // 0
    129. std::cout << unique_map1.size() << std::endl; // 4
    130. unique_map1.clear();
    131. std::cout << unique_map1.empty() << std::endl; // 1
    132. std::cout << unique_map1.size() << std::endl; // 0
    133. return 0;
    134. }

         4. my_multimap

    1. // my_multimap.h
    2. #include
    3. #include
    4. template<typename Key, typename Value>
    5. class my_multimap
    6. {
    7. typedef std::pair ValueType;
    8. typedef std::_Rb_tree, std::less> Rb_type;
    9. typedef typename Rb_type::iterator Iterator;
    10. public:
    11. my_multimap()
    12. {
    13. }
    14. template<typename InputIterator>
    15. my_multimap(InputIterator first, InputIterator last)
    16. {
    17. rb_tree._M_insert_equal(first, last);
    18. }
    19. my_multimap(std::initializer_list init_list)
    20. {
    21. rb_tree._M_insert_equal(init_list.begin(), init_list.end());
    22. }
    23. ~my_multimap()
    24. {
    25. }
    26. Iterator begin()
    27. {
    28. return rb_tree.begin();
    29. }
    30. Iterator end()
    31. {
    32. return rb_tree.end();
    33. }
    34. void clear()
    35. {
    36. rb_tree.clear();
    37. }
    38. void insert(ValueType& val)
    39. {
    40. rb_tree._M_insert_equal(val);
    41. }
    42. void insert(ValueType&& val)
    43. {
    44. rb_tree._M_insert_equal(val);
    45. }
    46. template<typename ... Args>
    47. void emplace(Args&& ... args)
    48. {
    49. rb_tree._M_emplace_equal(std::forward(args)...);
    50. }
    51. void erase(Iterator iter)
    52. {
    53. rb_tree.erase(iter);
    54. }
    55. std::size_t count(Key& key)
    56. {
    57. return rb_tree.count(key);
    58. }
    59. std::size_t count(Key&& key)
    60. {
    61. return rb_tree.count(key);
    62. }
    63. Iterator find(Key& key)
    64. {
    65. return rb_tree.find(key);
    66. }
    67. Iterator find(Key&& key)
    68. {
    69. return rb_tree.find(key);
    70. }
    71. bool empty()
    72. {
    73. return rb_tree.empty();
    74. }
    75. std::size_t size()
    76. {
    77. return rb_tree.size();
    78. }
    79. void erase(Key& key)
    80. {
    81. rb_tree.erase(key);
    82. }
    83. void erase(Key&& key)
    84. {
    85. rb_tree.erase(key);
    86. }
    87. private:
    88. Rb_type rb_tree;
    89. };
    90. // main.cpp
    91. #include
    92. #include"my_multimap.h"
    93. int main()
    94. {
    95. // 1. 构造函数
    96. my_multimap<int, std::string> multi_map1;
    97. my_multimap<int, std::string> multi_map2 = {{1, "a"}, {22, "bb"}, {3, "c"}};
    98. my_multimap<int, std::string> multi_map3(multi_map2.begin(), multi_map2.end());
    99. // 2. 容器修改
    100. multi_map1.insert({5, "e"});
    101. multi_map1.insert({6, "f"});
    102. multi_map1.emplace(7, "g");
    103. multi_map1.emplace(7, "g");
    104. multi_map1.emplace(7, "g");
    105. multi_map1.emplace(8, "h");
    106. multi_map1.insert({16, "ff"});
    107. multi_map1.erase(16);
    108. // 3. 容器访问
    109. std::cout << multi_map1.count(6) << std::endl; // 1
    110. auto item_iter1 = multi_map1.find(6);
    111. std::cout << (item_iter1 == multi_map1.end()) << std::endl; // 0
    112. std::cout << item_iter1->first << ", " << item_iter1->second << std::endl; // 6, f
    113. // 4. 容器容量
    114. std::cout << multi_map1.empty() << std::endl; // 0
    115. std::cout << multi_map1.size() << std::endl; // 6
    116. multi_map1.clear();
    117. std::cout << multi_map1.empty() << std::endl; // 1
    118. std::cout << multi_map1.size() << std::endl; // 0
    119. return 0;
    120. }

  • 相关阅读:
    网络安全(黑客)——自学2024
    花 30 美金请 AI 画家弄了个 logo,网友:画得非常好,下次别画了!
    java并发编程-实现线程的方法
    老卫带你学---leetcode刷题(240. 搜索二维矩阵 II)
    [Chrome插件开发]监听网页请求和响应
    三年,能否成为一名真正的架构师
    【MySQL】存储引擎
    中电金信技术实践|Redis哨兵原理及安装部署分享
    Java 实例 - 字符串小写转大写和测试两个字符串区域是否相等
    ElasticSearch 之 文本搜索
  • 原文地址:https://blog.csdn.net/qq_33775774/article/details/133484870