• 中级C++:map和set的迷你实现


    基建改造

    • 由于set使用的是K。map使用的K是pair<k,v>中的first,需要新增的第二个模板参数 T,来确定是用的是哪一种类型。
    • 由于红黑树这个类模板,也不知道这个类型到底具体是什么,所以再增加一个仿函数类型模板参数,获取K的类型。
    template<class T>
    struct RBTreeNode
    {
    	RBTreeNode* _left;
    	RBTreeNode* _right;
    	RBTreeNode* _parent;
    	T _data;
    	Colour _col;
    
    	RBTreeNode(const T& data)
    		:_left(nullptr)
    		, _right(nullptr)
    		, _parent(nullptr)
    		, _data(data)
    		, _col(RED)
    	{
    	}
    	
    };
    
    	template<class K, class T,class KeyofT>
    	class RBTree
    	{
    		....
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    红黑树的迭代器

    • 用一个节点的指针初始化成迭代器,实现对STL所有容器进行统一方式的访问。
    • 老三样,T,T&,T*;iterator要确保和官方迭代器名字一致就可以用范围for。
    • *it(迭代器),拿到这个指针里面的数据。
    • != 就是两个节点的指针不相等
    • 红黑树的++:访问到容器的下一个节点:
      • 红黑树的begin则应该是中序里最左边的一个节点。
      • ++,看begin 的右侧有没有节点,有的话,找右子树里面最左面的一个。
      • 如果右子树的左边没有,则代表当前节点就是右子树的最小值;再++;再看右子树的右侧有没有,…循环
      • 再++,右子树左侧没有,右侧也没有:代表我这一层的左子树右子树访问结束。返回上一层;
      • 由于这一层是从上一层的左子树下来的,要看当前节点是不是双亲结点的左侧;
      • 不是则一直迭代往上走;是就返回双亲结点…
    template<class T, class Ref, class Ptr>
    struct RBTreeiterator   //类模板
    {
    	typedef RBTreeNode<T> Node;...
    	typedef RBTreeiterator<T, Ref, Ptr> Self;  
    	Node* _node;
    
    	RBTreeiterator(Node* node = nullptr)
    		:_node(node)
    	{
    	}
    
    	//*it 对一个指针解引用,取到的是节点里面的数据
    	Ref operator*()
    	{
    		return _node->_data;
    	}
    	Ptr operator->()
    	{
    		return &_node->_data;
    	}
    
    	//红黑树迭代器的前置++ 返回是自增以后的迭代器
    	Self& operator++()
    	{
    		if (_node->_right)
    		{
    			//右边存在,找右子树最左边的那个节点
    			Node* subRL = _node->_right;
    			//左子树到头了,此刻的subRL就是右子树里最左边的节点
    			while (subRL->_left)
    			{
    				subRL = subRL->_left;
    			}
    			_node = subRL;
    		}
    		else//代表当前这个子树访问完了,左 中 右 找此根的父亲,该父亲的左孩子是此根。
    		{
    			Node* cur = _node;
    			Node* parent = _node->_parent;
    			while (parent&& parent->_right==cur)
    			{
    				cur = parent;
    				parent = cur->_parent;
    			}
    
    			_node = parent;
    		}
    		return *this;
    	}
    	bool operator!=(const Self& s)const
    	{
    		return _node != s._node;
    	}
    	bool operator==(const Self& s) const
    	{
    		return _node == s._node;
    	}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    封装成map

    • 有了第二个模板参数,为什么还要第一个模板参数K呢;因为查找是按K值查找的…且STL原版就是这么设计的…
    • 迭代器和插入用的都是红黑树的。参考官方文档可知:插入返回的时pair类型,第一个参数是插入结点或值相等结点的迭代器和布尔值。
    • 还有一个 [ ] 重载,返回的时pair<k,v>里面V的引用。make_pair(“呵呵哒”,“我C”)–“我C”
    • typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;告诉编译器那一长托是个类型,不然编不过去。
    template < class K, class V>
    	class map
    	{
    		struct MapKeyOfT //把 K 提取出来
    		{
    			const K& operator()(const pair<const K, V>& kv)
    			{
    				return kv.first;
    			}
    		};
    	public:
    		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
    
    		iterator begin()
    		{
    			return _t.begin();
    		}
    
    		iterator end()
    		{
    			return _t.end();
    		}
    //iterator --》 结点的数据类型
    		pair<iterator, bool> insert(const pair<const K, V>& kv)
    		{
    			return _t.Insert(kv);
    		}
    
    		V& operator[](const K& key)
    		{
    			pair<iterator, bool> ret = _t.Insert(make_pair(key, V()));
    			return ret.first->second;//省略了一个-》
    		}
    	private:
    		RBTree<K, pair<const K, V>, MapKeyOfT> _t;//使用模板显式的声明使用的类型
    	};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    红黑树的改造

    • T:set:int,char…;map:pair<int,int>…
    template<class K, class T, class KeyOfT>
    class RBTree
    {
    	typedef RBTreeNode<T> Node; ....//T类型的节点
    public:
    	typedef RBTreeIterator<T, T&, T*> iterator;  .....
    	typedef RBTreeIterator<T, const T&, const T*> const_iterator;
    
    	iterator begin()
    	{
    		Node* left = _root;
    		while (left && left->_left)
    		{
    			left = left->_left;
    		}
    
    		//return left;
    		return iterator(left);
    	}
    
    	iterator end()
    	{
    		return iterator(nullptr);
    	}
    
    	RBTree()
    		:_root(nullptr)
    	{}
    	....
    	Node* Find(const K& key);
    	//插入
    	pair<iterator, bool> Insert(const T& data)
    	{
    		if (_root == nullptr)
    		{
    				......
    			return make_pair(iterator(_root), true);
    		}
    
    		Node* parent = nullptr;
    		Node* cur = _root;
    
    		KeyOfT kot;  			/仿函数使用场景   
    		while (cur)
    		{
    			.......
    			if (kot(cur->_data) < kot(data))
    			{
    				parent = cur;
    				cur = cur->_right;
    			}
    			else if (kot(cur->_data) > kot(data))
    			{
    				parent = cur;
    				cur = cur->_left;
    			}
    			else
    			{
    				return make_pair(iterator(cur), false);
    			}
    		}
    
    		// 新增节点,颜色是红色,可能破坏规则3,产生连续红色节点
    		cur = new Node(data);
    		Node* newnode = cur;   //便于返回迭代器...
    		cur->_col = RED;
    		........
    		_root->_col = BLACK;
    		return make_pair(iterator(newnode), true);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    封装成set

    • 第二个模板参数也传K…
    template < class K>
    	class set
    	{
    		struct SetKeyOfT  
    		{
    			const K& operator()(const K& key)
    			{
    				return key;
    			}
    		};
    	public:
    		typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
    
    		iterator begin()
    		{
    			return _t.begin();
    		}
    
    		iterator end()
    		{
    			return _t.end();
    		}
    
    		pair<iterator, bool> insert(const K& key)
    		{
    			return _t.Insert(key);
    		}
    	private:
    		RBTree<K, K, SetKeyOfT> _t;
    	};
    ----仿函数使用场景..
    		KeyOfT kot;
    		while (cur)
    		{
    			if (kot(cur->_data) < kot(data))
    			{
    				parent = cur;
    				cur = cur->_right;
    			}
    			else if (kot(cur->_data) > kot(data))
    			{
    				parent = cur;
    				cur = cur->_left;
    			}
    ....
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    编者寄语

    现在一只半截的buff,迟早凉凉…该哈希了…

  • 相关阅读:
    STC89C51基础及项目第15天:小车测速、添加语言识别控制
    Java子类继承父类私有方法属性问题讲解
    读博时的建议或心得
    HTML跳动的爱心
    数字化浪潮,中小企业的降本增效之举
    Spring源码:ApplicationContextAware和BeanFactoryAware理解BeanFactory和Aware
    vue_Delete `␍`eslint(prettier/prettier)
    【租车骑绿道】python实现-附ChatGPT解析
    妇科检查,到底查什么?
    2、乐趣国学——“君子慎独”
  • 原文地址:https://blog.csdn.net/WTFamer/article/details/125492504