【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. }


相关文章
|
6天前
|
存储 安全 Java
java集合框架复习----(4)Map、List、set
这篇文章是Java集合框架的复习总结,重点介绍了Map集合的特点和HashMap的使用,以及Collections工具类的使用示例,同时回顾了List、Set和Map集合的概念和特点,以及Collection工具类的作用。
java集合框架复习----(4)Map、List、set
|
16天前
|
存储 JavaScript 前端开发
ES6新特性(四): Set 和 Map
ES6新特性(四): Set 和 Map
|
8天前
|
关系型数据库 C++ 容器
【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——红黑树
【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——红黑树
15 0
|
1月前
|
C++ 容器
【C++】map和set封装
【C++】map和set封装
23 2
|
1月前
|
存储 C++ 容器
【C++】map和set深度讲解(下)
【C++】map和set深度讲解(下)
41 2
|
1月前
|
Java C++ Python
【C++】手撕红黑树
【C++】手撕红黑树
14 1
|
1月前
|
存储 C++ 容器
【C++】开散列实现unordered_map与unordered_set的封装
【C++】开散列实现unordered_map与unordered_set的封装
28 0
|
2月前
|
Dart
Dart之集合详解(List、Set、Map)
Dart之集合详解(List、Set、Map)
44 1
|
2月前
|
存储 JavaScript 前端开发
JavaScript进阶-Map与Set集合
【6月更文挑战第20天】JavaScript的ES6引入了`Map`和`Set`,它们是高效处理集合数据的工具。`Map`允许任何类型的键,提供唯一键值对;`Set`存储唯一值。使用`Map`时,注意键可以非字符串,用`has`检查键存在。`Set`常用于数组去重,如`[...new Set(array)]`。了解它们的高级应用,如结构转换和高效查询,能提升代码质量。别忘了`WeakMap`用于弱引用键,防止内存泄漏。实践使用以加深理解。
|
10天前
|
存储