【C++】-- STL之用红黑树模拟实现map和set(二)

简介: 【C++】-- STL之用红黑树模拟实现map和set

三、红黑树迭代器

map和set的迭代器的实现其实本质上是红黑树迭代器的实现,迭代器的实现需要定义模板类型、模板类型引用、模板类型指针。

1.红黑树中迭代器重命名

在红黑树中重命名模板类型、模板类型引用、模板类型指针,定义为public,外部就能使用iterator了:

1. template<class K, class T, class KeyOfT>
2. class RBTree
3. {
4.  typedef RBTreeNode<T> Node;
5. 
6. public:
7.  typedef __TreeIterator<T, T&, T*> iterator;//模板类型、模板类型引用、模板类型指针
8. 
9. //红黑树函数...
10. 
11. private:
12.   Node* _root;
13. };

2.正向迭代器定义

红黑树的迭代器的本质是对节点指针进行封装,所以迭代器中只有封装红黑树节点指针这一个成员变量 。正向迭代器:

1. template<class T,class Ref,class ptr>
2. struct __TreeIterator
3. {
4.  typedef RBTreeNode<T> Node;
5.  typedef __TreeIterator<T, Ref, ptr> Self;
6. 
7.  Node* _node;//成员变量
8. 
9. };

3.迭代器构造

用节点指针构造正向迭代器:

1.  //构造函数
2.  __TreeIterator(Node* node)
3.    :_node(node)
4.  {}

4.正向迭代器重载*

Ref对正向迭代器解引用,返回节点数据引用:

1.  //* 解引用,返回节点数据
2.  Ref Operator*()
3.  {
4.    return _node->_data;
5.  }

5.正向迭代器重载->

Ptr对正向迭代器使用->,返回节点数据指针:

1.  //-> 返回节点数据地址
2.  Ptr Operator->()
3.  {
4.    return &_node->_data;
5.  }

6.正向迭代器重载==

判断节点是否相同

1.  //判断两个迭代器是否相同
2.  bool operator==(const Self& s)
3.  {
4.    return _node == s._node;//判断节点是否相同
5.  }

7.正向迭代器重载!=

判断节点是否不同

1.  //判断两个迭代器是否不同
2.  bool operator!=(const Self& s)
3.  {
4.    return _node != s._node;//判断节点是否不同
5.  }

8.正向迭代器++

①当节点的右子树不为空时,++就要走到右子树的最左节点

②当节点的右子树为空时,++就要走到节点的父亲

1.  //红黑树迭代器的++也就是红黑树的++
2.  Self operator++()
3.  {
4.    //1.右子树不为空
5.    if (_node->_right)
6.    {
7.      //下一个访问的是右树的中序第一个节点(即右子树最左节点)。
8.      Node* left = _node->_right;
9. 
10.       //找最左节点
11.       while (left->_left)
12.       {
13.         left = left->_left;
14.       }
15.       _node = left;
16.     }
17.     else//2.右子树为空,下一个访问的就是当前节点的父亲
18.     {
19.       Node* cur = _node;
20.       Node* parent = cur->_parent;
21.       while (parent && cur == parent->_right)
22.       {
23.         cur = cur->_parent;
24.         parent = parent->_parent;
25.       }
26.       _node = parent;
27.     }
28. 
29.     return *this;
30.   }
31. };

9.正向迭代器--

①当节点的左子树不为空时,++就要走到左子树的最右节点

②当节点的左子树为空时,++就要走到节点的父亲

1.  //红黑树迭代器的--也就是红黑树的--
2.  Self operator--()
3.  {
4.    //1.左子树不为空
5.    if (_node->_left)
6.    {
7.      //下一个访问的是左树的中序左后节点(即做子树最右节点)。
8.      Node* right = _node->_left;
9. 
10.       //找最右节点
11.       while (right->_right)
12.       {
13.         right = right->_right;
14.       }
15.       _node = right;
16.     }
17.     else//2.左子树为空,下一个访问的就是当前节点的父亲
18.     {
19.       Node* cur = _node;
20.       Node* parent = cur->_parent;
21.       while (parent && cur == parent->_left)
22.       {
23.         cur = cur->_parent;
24.         parent = parent->_parent;
25.       }
26.       _node = parent;
27.     }
28. 
29.     return *this;
30.   }

10.红黑树中实现迭代器

实现begin( )找最左节点,end( )最后一个节点的下一个位置

1. template<class K, class T, class KeyOfT>
2. class RBTree
3. {
4.  typedef RBTreeNode<T> Node;
5. 
6. public:
7.  typedef __TreeIterator<T, T&, T*> iterator;//模板类型、模板类型引用、模板类型指针
8. 
9. //找最左节点
10.   iterator begin()
11.   {
12.     Node* left = _root;
13.     while (left && left->_left)
14.     {
15.       left = left->_left;
16.     }
17. 
18.     return iterator(left)//返回最左节点的正向迭代器
19.   }
20. 
21.   //结束
22.   iterator end()
23.   {
24.     return iterator(nullptr);
25.   }
26. 
27. private:
28.   Node* _root;
29. };

四、set模拟实现

调用红黑树对应接口实现set,插入和查找函数返回值当中的节点指针改为迭代器:

1. #pragma once
2. #include "RBTree.h"
3. namespace delia
4. {
5.  template<class K>
6.  class set
7.  {
8.    //仿函数,获取set的key
9.    struct SetKeyOfT
10.     {
11.       const K& operator()(const K& key)
12.       {
13.         return key;
14.       }
15.     };
16.   public:
17.     typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
18. 
19.     //迭代器开始
20.     iterator begin()
21.     {
22.       return _t.begin();
23.     }
24. 
25.     //迭代器结束
26.     iterator end()
27.     {
28.       return _t.end();
29.     }
30. 
31.     //插入函数
32.     pair<iterator,bool> insert(const K& key)
33.     {
34. 
35.       return _t.Insert(key);
36.     }
37. 
38.     //查找
39.     iterator find(const K& key)
40.     {
41.       return _t.find(key);
42.     }
43.   private:
44.     RBTree<K, K, SetKeyOfT> _t;
45.   };
46. }

五、map模拟实现

调用红黑树对应接口实现map,插入和查找函数返回值当中的节点指针改为迭代器,增加operator[ ]的重载:

1. #pragma once
2. #include "RBTree.h"
3. namespace delia
4. {
5.  template<class K, class V>
6.  class map
7.  {
8.    //仿函数,获取map的first
9.    struct MapKeyOfT
10.     {
11.       const K& operator()(const pair<const K, V>& kv)
12.       {
13.         return kv.first;
14.       }
15.     };
16.   public:
17.     typedef typename RBTree<K, K, MapKeyOfT>::iterator iterator;
18. 
19.     //迭代器开始
20.     iterator begin()
21.     {
22.       return _t.begin();
23.     }
24. 
25.     //迭代器结束
26.     iterator end()
27.     {
28.       return _t.end();
29.     }
30. 
31.     //插入
32.     pair<iterator, bool> insert(const pair<const K, V>& kv)
33.     {
34.       return _t.Insert(kv);
35.     }
36. 
37.     //重载operator[]
38.     V& operator[](const K& key)
39.     {
40.       pair<iterator, bool> ret = insert(make_pair(key, V()));
41.       iterator it = ret.first;
42.       return it->second;
43.     }
44. 
45.     //查找
46.     iterator find(const K& key)
47.     {
48.       return _t.find(key);
49.     }
50. 
51.   private:
52.     RBTree<K, pair<const K, V>, MapKeyOfT> _t;
53.   };
54. }


相关文章
|
1天前
|
编译器 容器
哈希表模拟封装unordered_map和unordered_set
哈希表模拟封装unordered_map和unordered_set
|
1天前
|
编译器 测试技术 计算机视觉
红黑树模拟封装map和set
红黑树模拟封装map和set
|
2月前
|
算法
你对Collection中Set、List、Map理解?
你对Collection中Set、List、Map理解?
79 18
你对Collection中Set、List、Map理解?
|
2月前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
2月前
|
存储 缓存 安全
只会“有序无序”?面试官嫌弃的List、Set、Map回答!
小米,一位热衷于技术分享的程序员,通过与朋友小林的对话,详细解析了Java面试中常见的List、Set、Map三者之间的区别,不仅涵盖了它们的基本特性,还深入探讨了各自的实现原理及应用场景,帮助面试者更好地准备相关问题。
71 20
|
3月前
|
存储 算法 C++
【C++】unordered_map(set)
C++中的`unordered`容器(如`std::unordered_set`、`std::unordered_map`)基于哈希表实现,提供高效的查找、插入和删除操作。哈希表通过哈希函数将元素映射到特定的“桶”中,每个桶可存储一个或多个元素,以处理哈希冲突。主要组成部分包括哈希表、哈希函数、冲突处理机制、负载因子和再散列,以及迭代器。哈希函数用于计算元素的哈希值,冲突通过开链法解决,负载因子控制哈希表的扩展。迭代器支持遍历容器中的元素。`unordered_map`和`unordered_set`的插入、查找和删除操作在理想情况下时间复杂度为O(1),但在冲突较多时可能退化为O(n)。
37 5
|
5月前
|
Go 定位技术 索引
Go 语言Map(集合) | 19
Go 语言Map(集合) | 19
|
5月前
|
存储 前端开发 API
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
该文章详细介绍了ES6中Set和Map数据结构的特性和使用方法,并探讨了它们在前端开发中的具体应用,包括如何利用这些数据结构来解决常见的编程问题。
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
|
6月前
|
存储 安全 Java
java集合框架复习----(4)Map、List、set
这篇文章是Java集合框架的复习总结,重点介绍了Map集合的特点和HashMap的使用,以及Collections工具类的使用示例,同时回顾了List、Set和Map集合的概念和特点,以及Collection工具类的作用。
java集合框架复习----(4)Map、List、set
|
6月前
|
Java
【Java集合类面试二十二】、Map和Set有什么区别?
该CSDN博客文章讨论了Map和Set的区别,但提供的内容摘要并未直接解释这两种集合类型的差异。通常,Map是一种键值对集合,提供通过键快速检索值的能力,而Set是一个不允许重复元素的集合。