首页 > 其他分享 >STL 改造红黑树 模拟封装set和map

STL 改造红黑树 模拟封装set和map

时间:2024-08-31 20:53:03浏览次数:13  
标签:node map set cur parent STL iterator root left

改造红黑树

目录

在初次看STL中实现红黑树的源码时有些不理解,然后自己尝试对set以RBTree<K,K>的方式封装红黑树的迭代器;实现过程发现,这样封装复用程度特别低,也特别冗余,因此才能领悟到STL源码实现红黑树复用时的精髓.下文将模拟STL的实现方式改造红黑树和封装map和set.

参考的STL版本为SGI30

适配STL迭代器的红黑树

红黑树数据操作的代码实现是旧版本的,新版本在上一篇博客中有详细分析.

本篇主要特点在迭代器适配上

基本结构

#pragma once

#include<assert.h>
#include<iostream>
using std::cout;
using std::endl;
using std::cin;
using std::pair;
using std::make_pair;
using std::string;


namespace test
{
	enum Colour { RED, BLACK };
	template<class T> struct RBTreeNode;
	template<class T, class Ref, typename Ptr> struct __RBTree_iterator;
	template<class K, class T, class keyOfT> class RBTree;
}

RBTreeNode

	template<class T> // T为key或pair,T是key或者key-value类型
	struct RBTreeNode
	{
		RBTreeNode* _left;
		RBTreeNode* _right;
		RBTreeNode* _parent;
		T _data; //data是key或pair
		Colour _col;

		RBTreeNode(const T& data)
			: _left(nullptr)
			, _right(nullptr)
			, _parent(nullptr)
			, _data(data)
			, _col(RED)
		{}
	};

__RBTree_iterator

template<class T, class Ref, typename Ptr>
	struct __RBTree_iterator
	{
		typedef RBTreeNode<T> node;
		node* _node;
		__RBTree_iterator(node* node)
			:_node(node)
		{}

		//首先,<class T, class Ref, class Ptr>这种写法能够提高复用性和灵活性(实现不同类型的迭代器)等,,库里迭代器都这么写
		//其次,模板参数中,T用于获取类型,Ref用于返回引用,Ptr用于返回指针

		using Self           = __RBTree_iterator<T,Ref,Ptr>;            //自己--实例化出下面两种迭代器
		using iterator       = __RBTree_iterator<T,T&,T*>;              //普通迭代器
		using const_iterator = __RBTree_iterator<T,const T&,const T*>;  //const迭代器
		__RBTree_iterator(const iterator& it) 
			:_node(it._node)
		{}
		//这个构造函数的作用,
	    //a.当迭代器被实例化成iterator时,他就是拷贝构造函数.      __RBTree_iterator<T,T&,T*>
		//b.当迭代器被实例化成const_iterator时,他是支持隐式类型转换的带参构造函数. __RBTree_iterator<T,const T&,const T*> 

		//这样实现的目的
	    // 能够复用普通迭代器,可以通过类型转换后直接实现出const迭代器


		//Ref为 T& 或 const T&, Ptr为 T* 或 const T*
		//typedef __RBTree_iterator<T, Ref, Ptr> Self;

		Ref operator*()
		{
			return _node->_data;
		}
		Ptr operator->()
		{
			return &(_node->_data);
		}
		bool operator!=(const Self& x)
		{
			return _node != x._node;
		}
    //前置++
    Self& operator++() {
        //此版本实现迭代器不需要判空,为空说明遍历结束,要么是用户错误使用
        Node* cur = _node;
        //1. 有右子树
        if (cur->_right) {
            //找右子树的最小结点
            Node* rightMin = cur->_right;
            while (rightMin->_left) {
                rightMin = rightMin->_left;
            }
            _node = rightMin;
        }
        //2. 没有右子树
        else {
            ////1.没有父亲,说明是根
            //Node* parent = cur->_parent;
            //if (parent == nullptr) {
            //    _node == nullptr;
            //}
            ////2.且我是父的左子树,说明父亲是下一个正序值
            //else if (parent->_left == cur) {
            //    _node = parent;
            //}
            ////3.或我是父亲的右子树,说明走完了当前最小分支祖先这棵树.迭代往上
            //else if (parent->_right == cur) {
            //    while (parent && cur != parent->_left) {
            //        cur = parent;
            //        parent = parent->_parent;
            //    }
            //    _node = parent;
            //}
            //else {
            //    asssert(false);
            //}

            //上面3种情况可以合并成一种情况:找最近的不是右孩子的祖父
            Node* parent = cur->_parent;
            while (parent && cur != parent->_left) {
                cur = parent;
                parent = parent->_parent;
            }
            _node = parent;
        }
        return *this;
    }

    //后置++
    Self operator++(int) {
        Self tmp(_node);
        operator++();
        return tmp;
    }


    Self& operator--() {
        //将++反过来就是--
        Node* cur = _node;
        //左子树存在,就找最大
        if (cur->_left) {
            Node* leftMax = cur->_left;
            while (leftMax->_right) {
                leftMax = leftMax->_right;
            }
            _node = leftMax;
        }
        //2. 没有左子树
        else {
            Node* parent = cur->_parent;
            while (parent && cur != parent->_right) {
                cur = parent;
                parent = parent->_parent;
            }
            _node = parent;
        }
        return *this;
    }

    Self operator--(int) {
        Self tmp(_node);
        operator--();
        return tmp;
    }
	};

RBTree

	//参数K用在find,erase等,虽然K也可以被T取代了,但没必要,K更快
	template<class K, class T, class keyOfT> //库中还有1个compare,先不写了
	class RBTree
	{
	public:
		typedef RBTreeNode<T> node; //T是key或pair
	public:
		typedef __RBTree_iterator<T, T&, T*> iterator;
		typedef __RBTree_iterator<T, const T&, const T*> const_iterator;

		iterator begin()
		{
			node* cur = _root;
			while (cur && cur->_left)//不能走到空
			{
				cur = cur->_left;
			}
			return iterator(cur);//返回中序的第一个结点,最左结点
		}

		iterator end() //end是最一个位置的下一个
		{
			return iterator(nullptr);//暂时可以这么写
		}

		const_iterator begin()const
		{
			node* cur = _root;
			while (cur && cur->_left)
			{
				cur = cur->_left;
			}
			return iterator(cur);
		}

		const_iterator end() const
		{
			return iterator(nullptr);
		}

	private:
		node* _root = nullptr;
	public:
		node* find(const K& key)
		{
			keyOfT kot;//kot是个仿函数,根据不同参数返回不同的参数对象
			node* cur = _root;
			while (cur)
			{
				if (key < kot(cur->_data)) // -------------------------------------------- 只需要重载一个 '<' 或 '>' 就可以比较大小
				{
					cur = cur->_left;
				}
				else if (kot(cur->_data) < key) // --------------------------------------------只需要重载一个 '<' 或 '>' 就可以比较大小
				{
					cur = cur->_right;
				}
				else
				{
					return cur;
				}
			}
			return nullptr;
		}

		pair<iterator, bool> insert(const T& data)
		{
			if (!_root)
			{
				_root = new node(data);
				_root->_col = BLACK;
				return std::make_pair(iterator(_root), true);
			}
			
			keyOfT kot;

			node* cur = _root;
			node* parent = nullptr;
			while (cur)
			{
				if (kot(cur->_data) < kot(data)  ) // --------------------------------------------只需要重载一个 '<' 或 '>' 就可以比较大小
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (kot(data) < kot(cur->_data)) // --------------------------------------------只需要重载一个 '<' 或 '>' 就可以比较大小
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return std::make_pair(iterator(cur), false);
				}
			}
			cur = new node(data);
			if ( kot(parent->_data) < kot(data)) // --------------------------------------------
			{
				parent->_right = cur;
			}
			else
			{
				parent->_left = cur;
			}
			cur->_parent = parent;

			//调整/旋转
			node* newnode = cur;//调整过程cur会发生变化,将cur结点记住 -- 记住原来key的位置
			while (parent && parent->_col == RED)
			{
				node* g = parent->_parent;
				if (parent == g->_right)
				{
					node* u = g->_left;
					if (u && u->_col == RED)
					{
						g->_col = RED;
						parent->_col = BLACK;
						u->_col = BLACK;
						cur = g;
						parent = cur->_parent;
					}
					else
					{
						if (cur == parent->_right)
						{
							RotateL(g);
							parent->_col = BLACK;
							g->_col = RED;
						}
						else
						{
							RotateR(parent);
							RotateL(g);
							g->_col = RED;
							cur->_col = BLACK;
						}
						break;
					}

				}
				else
				{
					node* u = g->_right;
					if (u && u->_col == RED)
					{
						g->_col = RED;
						parent->_col = BLACK;
						u->_col = BLACK;
						cur = g;
						parent = cur->_parent;
					}
					else
					{
						if (cur == parent->_left)
						{
							RotateR(g);
							parent->_col = BLACK;
							g->_col = RED;
						}
						else
						{
							RotateL(parent);
							RotateR(g);
							g->_col = RED;
							cur->_col = BLACK;
						}
						break;
					}
				}
			}
			_root->_col = BLACK;
			return std::make_pair(iterator(newnode), true);
		}
	public:
		void InOrderTraversal()
		{
			_InOrderTraversal(_root);
		}

		bool isBalanceTree()
		{
			//需要判断3个规则
			//1.根为黑
			if (_root && _root->_col == RED)
			{
				cout << "错误:根是红色" << endl;
				return false;
			}

			//2.不能有连续得红
			//3.黑同
			int benchmark = 0;
			node* cur = _root;
			while (cur)
			{
				if (cur->_col == BLACK)
				{
					++benchmark;
				}
				cur = cur->_left;
			}
			return _check(_root, 0, benchmark);
		}

		int Height()
		{
			return _Height(_root);
		}
		~RBTree()
		{
			Destroy(_root);
		}

	private:
		void Destroy(node*& root)
		{
			if (!root)
			{
				return;
			}
			Destroy(root->_left);
			Destroy(root->_right);
			delete root;
			root = nullptr;
		}

		bool _check(node* root, int blackNum, int benchmark)
		{
			keyOfT kot;
			if (!root) //
			{
				if (blackNum != benchmark)
				{
					cout << "错误:存在不同路径的黑色结点数量不相同" << endl;
					return false;
				}
				return true;
			}

			if (root->_col == BLACK)
			{
				++blackNum;
			}

			if (root->_col == RED && root->_parent->_col == RED)
			{
				cout << kot(root->_data) << " 错误,与父节点同时为红色"; // --------------------------------------------
				return false;
			}

			return _check(root->_left, blackNum, benchmark) && _check(root->_right, blackNum, benchmark);
		}

		int _Height(node* root)
		{
			if (!root)
			{
				return 0;
			}
			int leftH = _Height(root->_left);
			int rightH = _Height(root->_right);

			return leftH > rightH ? leftH + 1 : rightH + 1;
		}

		void _InOrderTraversal(node* root)
		{
			keyOfT kot;
			if (root == nullptr)
			{
				return;
			}
			_InOrderTraversal(root->_left);
			cout << kot(root->_data) << " "; // --------------------------------------------
			_InOrderTraversal(root->_right);
		}

		void RotateL(node* parent)
		{
			node* subR = parent->_right;
			node* subRL = subR->_left;

			parent->_right = subRL;
			if (subRL)
			{
				subRL->_parent = parent;
			}

			node* pparent = parent->_parent;

			subR->_left = parent;
			parent->_parent = subR;

			if (!pparent)
			{
				_root = subR;
				_root->_parent = nullptr;
			}
			else
			{
				if (pparent->_left == parent)
				{
					pparent->_left = subR;
				}
				else
				{
					pparent->_right = subR;
				}
				subR->_parent = pparent;
			}
		}

		void RotateR(node* parent)
		{
			node* subL = parent->_left;
			node* subLR = subL->_right;

			parent->_left = subLR;
			if (subLR)
			{
				subLR->_parent = parent;
			}

			node* pparent = parent->_parent;

			subL->_right = parent;
			parent->_parent = subL;


			if (parent == _root)
			{
				_root = subL;
				_root->_parent = nullptr;
			}
			else
			{
				if (pparent->_left == parent)
				{
					pparent->_left = subL;
				}
				else
				{
					pparent->_right = subL;
				}
				subL->_parent = pparent;
			}
		}
	};

完整代码

#pragma once

#include<assert.h>
#include<iostream>
using std::cout;
using std::endl;
using std::cin;
using std::pair;
using std::make_pair;
using std::string;


namespace test
{

	//与库中的RBT差异
	/**
	 *
	 * 库中还有结点数量 count
	 *
	 * 库中RBT是带头结点哨兵卫的,头结点的左是中序第一个(最小结点),右节点是中序的最后一个(最大结点),
	 * 哨兵卫的parent指向根节点,根节点的parent指向哨兵卫
	 *
	 * 库中的begin直接取head的left -- 函数:leftmost() //最左结点
	 * 库中的end 是head的right -- 不是rightmost,rightmost是最右结点,end是最右结点的下一个
	 * 库中的end 需要判断一下,防止只有左子树的歪脖子树时,end == head->right,死循环
	 *
	 * 和库的区别就是end,库的end能走回到head,我的不能,只能走到空就没了d
	 *
	 */


	enum Colour { RED, BLACK };

	template<class T> //T是什么,为什么只传T? T为key或pair,T是key或者key-value类型
	struct RBTreeNode
	{
		RBTreeNode* _left;
		RBTreeNode* _right;
		RBTreeNode* _parent;
		T _data; //data是key或pair
		Colour _col;

		RBTreeNode(const T& data)
			: _left(nullptr)
			, _right(nullptr)
			, _parent(nullptr)
			, _data(data)
			, _col(RED)
		{}
	};
	//const_iterator<T,const T&,const T*>
	//iterator<T, T&, T*>

	template<class T, class Ref, typename Ptr>
	struct __RBTree_iterator
	{
		typedef RBTreeNode<T> node;
		node* _node;
		__RBTree_iterator(node* node)
			:_node(node)
		{}

		//首先,<class T, class Ref, class Ptr>这种写法能够提高复用性和灵活性(实现不同类型的迭代器)等,,库里迭代器都这么写
		//其次,模板参数中,T用于获取类型,Ref用于返回引用,Ptr用于返回指针

		using Self           = __RBTree_iterator<T,Ref,Ptr>;            //自己--实例化出下面两种迭代器
		using iterator       = __RBTree_iterator<T,T&,T*>;              //普通迭代器
		using const_iterator = __RBTree_iterator<T,const T&,const T*>;  //const迭代器
		__RBTree_iterator(const iterator& it) 
			:_node(it._node)
		{}
		//这个构造函数的作用,
	    //a.当迭代器被实例化成iterator时,他就是拷贝构造函数.      __RBTree_iterator<T,T&,T*>
		//b.当迭代器被实例化成const_iterator时,他是支持隐式类型转换的带参构造函数. __RBTree_iterator<T,const T&,const T*> 

		//这样实现的目的
	    // 能够复用普通迭代器,可以通过类型转换后直接实现出const迭代器


		//Ref为 T& 或 const T&, Ptr为 T* 或 const T*
		//typedef __RBTree_iterator<T, Ref, Ptr> Self;

		Ref operator*()
		{
			return _node->_data;
		}
		Ptr operator->()
		{
			return &(_node->_data);
		}
		bool operator!=(const Self& x)
		{
			return _node != x._node;
		}
    //前置++
    Self& operator++() {
        //此版本实现迭代器不需要判空,为空说明遍历结束,要么是用户错误使用
        Node* cur = _node;
        //1. 有右子树
        if (cur->_right) {
            //找右子树的最小结点
            Node* rightMin = cur->_right;
            while (rightMin->_left) {
                rightMin = rightMin->_left;
            }
            _node = rightMin;
        }
        //2. 没有右子树
        else {
            ////1.没有父亲,说明是根
            //Node* parent = cur->_parent;
            //if (parent == nullptr) {
            //    _node == nullptr;
            //}
            ////2.且我是父的左子树,说明父亲是下一个正序值
            //else if (parent->_left == cur) {
            //    _node = parent;
            //}
            ////3.或我是父亲的右子树,说明走完了当前最小分支祖先这棵树.迭代往上
            //else if (parent->_right == cur) {
            //    while (parent && cur != parent->_left) {
            //        cur = parent;
            //        parent = parent->_parent;
            //    }
            //    _node = parent;
            //}
            //else {
            //    asssert(false);
            //}

            //上面3种情况可以合并成一种情况:找最近的不是右孩子的祖父
            Node* parent = cur->_parent;
            while (parent && cur != parent->_left) {
                cur = parent;
                parent = parent->_parent;
            }
            _node = parent;
        }
        return *this;
    }

    //后置++
    Self operator++(int) {
        Self tmp(_node);
        operator++();
        return tmp;
    }


    Self& operator--() {
        //将++反过来就是--
        Node* cur = _node;
        //左子树存在,就找最大
        if (cur->_left) {
            Node* leftMax = cur->_left;
            while (leftMax->_right) {
                leftMax = leftMax->_right;
            }
            _node = leftMax;
        }
        //2. 没有左子树
        else {
            Node* parent = cur->_parent;
            while (parent && cur != parent->_right) {
                cur = parent;
                parent = parent->_parent;
            }
            _node = parent;
        }
        return *this;
    }

    Self operator--(int) {
        Self tmp(_node);
        operator--();
        return tmp;
    }
	};

	//参数K用在find,erase等,虽然K也可以被T取代了,但没必要,K更快
	template<class K, class T, class keyOfT> //库中还有1个compare,先不写了
	class RBTree
	{
	public:
		typedef RBTreeNode<T> node; //T是key或pair
	public:
		typedef __RBTree_iterator<T, T&, T*> iterator;
		typedef __RBTree_iterator<T, const T&, const T*> const_iterator;

		iterator begin()
		{
			node* cur = _root;
			while (cur && cur->_left)//不能走到空
			{
				cur = cur->_left;
			}
			return iterator(cur);//返回中序的第一个结点,最左结点
		}

		iterator end() //end是最一个位置的下一个
		{
			return iterator(nullptr);//暂时可以这么写
		}

		const_iterator begin()const
		{
			node* cur = _root;
			while (cur && cur->_left)
			{
				cur = cur->_left;
			}
			return iterator(cur);
		}

		const_iterator end() const
		{
			return iterator(nullptr);
		}

	private:
		node* _root = nullptr;
	public:
		node* find(const K& key)
		{
			keyOfT kot;//kot是个仿函数,根据不同参数返回不同的参数对象
			node* cur = _root;
			while (cur)
			{
				if (key < kot(cur->_data)) // -------------------------------------------- 只需要重载一个 '<' 或 '>' 就可以比较大小
				{
					cur = cur->_left;
				}
				else if (kot(cur->_data) < key) // --------------------------------------------只需要重载一个 '<' 或 '>' 就可以比较大小
				{
					cur = cur->_right;
				}
				else
				{
					return cur;
				}
			}
			return nullptr;
		}

		pair<iterator, bool> insert(const T& data)
		{
			if (!_root)
			{
				_root = new node(data);
				_root->_col = BLACK;
				return std::make_pair(iterator(_root), true);
			}
			
			keyOfT kot;

			node* cur = _root;
			node* parent = nullptr;
			while (cur)
			{
				if (kot(cur->_data) < kot(data)  ) // --------------------------------------------只需要重载一个 '<' 或 '>' 就可以比较大小
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (kot(data) < kot(cur->_data)) // --------------------------------------------只需要重载一个 '<' 或 '>' 就可以比较大小
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return std::make_pair(iterator(cur), false);
				}
			}
			cur = new node(data);
			if ( kot(parent->_data) < kot(data)) // --------------------------------------------
			{
				parent->_right = cur;
			}
			else
			{
				parent->_left = cur;
			}
			cur->_parent = parent;

			//调整/旋转
			node* newnode = cur;//调整过程cur会发生变化,将cur结点记住 -- 记住原来key的位置
			while (parent && parent->_col == RED)
			{
				node* g = parent->_parent;
				if (parent == g->_right)
				{
					node* u = g->_left;
					if (u && u->_col == RED)
					{
						g->_col = RED;
						parent->_col = BLACK;
						u->_col = BLACK;
						cur = g;
						parent = cur->_parent;
					}
					else
					{
						if (cur == parent->_right)
						{
							RotateL(g);
							parent->_col = BLACK;
							g->_col = RED;
						}
						else
						{
							RotateR(parent);
							RotateL(g);
							g->_col = RED;
							cur->_col = BLACK;
						}
						break;
					}

				}
				else
				{
					node* u = g->_right;
					if (u && u->_col == RED)
					{
						g->_col = RED;
						parent->_col = BLACK;
						u->_col = BLACK;
						cur = g;
						parent = cur->_parent;
					}
					else
					{
						if (cur == parent->_left)
						{
							RotateR(g);
							parent->_col = BLACK;
							g->_col = RED;
						}
						else
						{
							RotateL(parent);
							RotateR(g);
							g->_col = RED;
							cur->_col = BLACK;
						}
						break;
					}
				}
			}
			_root->_col = BLACK;
			return std::make_pair(iterator(newnode), true);
		}
	public:
		void InOrderTraversal()
		{
			_InOrderTraversal(_root);
		}

		bool isBalanceTree()
		{
			//需要判断3个规则
			//1.根为黑
			if (_root && _root->_col == RED)
			{
				cout << "错误:根是红色" << endl;
				return false;
			}

			//2.不能有连续得红
			//3.黑同
			int benchmark = 0;
			node* cur = _root;
			while (cur)
			{
				if (cur->_col == BLACK)
				{
					++benchmark;
				}
				cur = cur->_left;
			}
			return _check(_root, 0, benchmark);
		}

		int Height()
		{
			return _Height(_root);
		}
		~RBTree()
		{
			Destroy(_root);
		}

	private:
		void Destroy(node*& root)
		{
			if (!root)
			{
				return;
			}
			Destroy(root->_left);
			Destroy(root->_right);
			delete root;
			root = nullptr;
		}

		bool _check(node* root, int blackNum, int benchmark)
		{
			keyOfT kot;
			if (!root) //
			{
				if (blackNum != benchmark)
				{
					cout << "错误:存在不同路径的黑色结点数量不相同" << endl;
					return false;
				}
				return true;
			}

			if (root->_col == BLACK)
			{
				++blackNum;
			}

			if (root->_col == RED && root->_parent->_col == RED)
			{
				cout << kot(root->_data) << " 错误,与父节点同时为红色"; // --------------------------------------------
				return false;
			}

			return _check(root->_left, blackNum, benchmark) && _check(root->_right, blackNum, benchmark);
		}

		int _Height(node* root)
		{
			if (!root)
			{
				return 0;
			}
			int leftH = _Height(root->_left);
			int rightH = _Height(root->_right);

			return leftH > rightH ? leftH + 1 : rightH + 1;
		}

		void _InOrderTraversal(node* root)
		{
			keyOfT kot;
			if (root == nullptr)
			{
				return;
			}
			_InOrderTraversal(root->_left);
			cout << kot(root->_data) << " "; // --------------------------------------------
			_InOrderTraversal(root->_right);
		}

		void RotateL(node* parent)
		{
			node* subR = parent->_right;
			node* subRL = subR->_left;

			parent->_right = subRL;
			if (subRL)
			{
				subRL->_parent = parent;
			}

			node* pparent = parent->_parent;

			subR->_left = parent;
			parent->_parent = subR;

			if (!pparent)
			{
				_root = subR;
				_root->_parent = nullptr;
			}
			else
			{
				if (pparent->_left == parent)
				{
					pparent->_left = subR;
				}
				else
				{
					pparent->_right = subR;
				}
				subR->_parent = pparent;
			}
		}

		void RotateR(node* parent)
		{
			node* subL = parent->_left;
			node* subLR = subL->_right;

			parent->_left = subLR;
			if (subLR)
			{
				subLR->_parent = parent;
			}

			node* pparent = parent->_parent;

			subL->_right = parent;
			parent->_parent = subL;


			if (parent == _root)
			{
				_root = subL;
				_root->_parent = nullptr;
			}
			else
			{
				if (pparent->_left == parent)
				{
					pparent->_left = subL;
				}
				else
				{
					pparent->_right = subL;
				}
				subL->_parent = pparent;
			}
		}
	};
}

封装的set

红黑树改造完成后,封装set和map就比较简单了,基本上都是套用红黑树的功能,特别方便,这也体会到了实现STL的大佬们的厉害.

#pragma once

#include"RBT.hpp"
namespace test
{

	template<class K>
	class set
	{

	private:
		struct setKeyOfT//取出RBT的类型T中的key
		{
			const K& operator()(const K& key) 
			{
				return key; 
			}
		};
	private:
		RBTree< K, K, setKeyOfT>_t;
	public:
		//使用类域的要加typename,以防和静态变量冲突
		typedef typename RBTree<K, K, setKeyOfT>::const_iterator iterator; //普通迭代器
		typedef typename RBTree<K, K, setKeyOfT>::const_iterator const_iterator; //const迭代器

		iterator begin()
		{
			return _t.begin(); //begin是普通迭代器,返回值是const,发生隐式类型转换(单参数)
			//如果有相应的构造函数,则支持隐式类型转换 ,但此时迭代器没有参数为迭代器的构造函数,需要添加
		}
		iterator end()
		{
			return _t.end();
		}

		const_iterator begin()const
		{
			return _t.begin();
		}
		const_iterator end()const
		{
			return _t.end();
		}

		

	public:
		pair<iterator, bool> insert(const K& key)
		{
			return _t.insert(key);
		}


	};

	void test_mySet1()
	{
		test::set<int> s;
		s.insert(2);
		s.insert(1);
		s.insert(3);

		set<int>::iterator it = s.begin();
		//while (it!=s.end())
		//{
		//	cout << *it << " ";
		//	++it;
		//}
		for (auto& e : s)
		{
			cout << e << " ";
		}
		cout << *++it << " ";
		cout << *--it << " ";
		cout << endl;
		//*it = 1;////不允许赋值,表达式必须是可以修改的左值 .不能给常量赋值
		

	}
}

封装的map

#pragma once

#include"RBT.hpp"
namespace test
{
	template<class K,class V>
	class map
	{
	private:
		struct mapKeyOfT
		{ 
			const K& operator()(const pair<const K,V>& kv) 
			{
				return kv.first; 
			}
		};
	private:
		RBTree<K, pair<const K, V>, mapKeyOfT> _t;
	public:
		typedef typename RBTree<K, pair<const K,V>, mapKeyOfT>::iterator iterator; 

		iterator begin()
		{
			return _t.begin();
		}
		iterator end()
		{
			return _t.end();
		}

	public:
		pair<iterator,bool> insert(const pair<const K, V>& kv)
		{
			return _t.insert(kv);
		}

		V& operator[](const K& key)
		{
			pair<iterator,bool> ret = insert(make_pair(key, V()));
			return ret.first->second;
		}

	};

	void test_myMap1()
	{
		test::map<int, int> m;
		m.insert(std::make_pair(1, 1));
		m.insert(std::make_pair(3, 3));
		m.insert(std::make_pair(2, 2));
		test::map<int,int>::iterator it = m.begin();
		//while (it != m.end())
		//{
		//	cout << it->first << " ";
		//	++it;
		//}
		for (auto e : m)
		{
			cout << e.first << " ";
		}

		cout << (++it)->first << " ";
		cout << (--it)->first << " ";
		cout << endl;

		//it->second = 1; //可以赋值
		//it->first = 1;//不允许赋值,表达式必须是可以修改的左值 .不能给常量赋值
	}

	void test_myMap2()
	{
		//map的使用
		map<std::string, std::string>  dict;
		dict.insert(std::pair<std::string, std::string>("sort", "排序")); //匿名对象插入
		dict.insert(std::make_pair("string", "字符串"));    //pair封装插入
		dict.insert(std::make_pair("count", "计数"));
		dict.insert(std::make_pair("count", "(计数)")); //插入失败的
		auto it = dict.begin();
		while (it != dict.end())
		{
			cout << it->first << ":" << it->second << endl;
			++it;
		}
	}

	void test_myMap3()
{
	std::string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜","苹果", "香蕉", "苹果", "香蕉" };
	map<std::string, int> countMap;
	/*for (auto e : arr)
	{
		auto ret = countMap.find(x);
		if (ret==countMap.end())
		{
			countMap.insert(std::pair<string, int>(x, 1));
		}
		else
		{
			++ret->second;
		}
	}*/

	for (auto& e : arr)
	{
		++countMap[e];
	}

	for (auto& s : countMap)
	{
		cout <<  s.first << ":" << s.second << endl;
	}
	}
}



标签:node,map,set,cur,parent,STL,iterator,root,left
From: https://www.cnblogs.com/DSCL-ing/p/18390555

相关文章

  • 集合及数据结构第十二节(上)———— 二叉搜索树和Map、Set详解
    系列文章目录集合及数据结构第十二节(上)————二叉搜索树和Map、Set详解二叉搜索树和Map、Set详解搜索树的概念二叉搜索树的实现性能分析和java类集的关系搜索的概念及场景模型关于Map的说明关于Map.Entry<K,V>的说明Map的常用方法说明TreeMap的使用案例Set的常见......
  • 深入解析 Go 中 Map
    0前言Go语言中的map是一种内建的数据结构,用于存储键值对。它类似于其他编程语言中的哈希表或字典,提供了快速的插入、删除和查找操作。本文将深入浅出介绍map基本概念、使用方式、核心原理、性能以及最佳实践,帮助读者更好的理解和使用map。如果您觉得有帮助,请关注我,另......
  • vtk 对 ct 图像三维重建并保存.stl到相关目录
    #include<vtkAutoInit.h> //初始化所需的VTK渲染模块 VTK_MODULE_INIT(vtkRenderingOpenGL2); VTK_MODULE_INIT(vtkInteractionStyle); #include<vtkSmartPointer.h> #include<vtkDICOMImageReader.h> #include<vtkMarchingCubes.h> #incl......
  • 网络安全公开数据集Maple-IDS,恶意流量检测数据集开放使用!
    MapleDataset枫叶数据集MapleDataset枫叶数据集由东北林业大学网络安全实验室(https://maple.nefu.edu.cn/lab/)公开发布,是用于入侵检测评估的数据集,其目的在于提升异常基础入侵检测系统(IDS)以及入侵预防系统(IPS)的性能与可靠性。在网络攻击愈发复杂的当下,拥有一个可靠且紧跟时代的......
  • C++STL~~list
    文章目录一、list的概念二、list的使用三、list的练习四、与vector的对比五、总结一、list的概念list是一种容器,实现了双向链表结构它具有以下特点:动态大小,可按需增减元素数量。高效的插入和删除操作,在任意位置插入和删除元素时间复杂度为O(1)。但随机访问元素......
  • [Redis]Intset
    intset小整数集合set集合容纳的元素都是整数并且元素个数较少时,Redis会使用intset来存储集合元素。intset是紧凑的数组结构,同时支持16位、32位和64位整数structintset<T>{ int32encoding;//决定整数位宽是16位、32位还是64 int32length;//元素个数 i......
  • list容器---深入探索STL中的双向链表
    目录一、引言二、list容器原理三、list容器的常用操作  1.创建list容器  2.添加元素  3.删除元素  4.访问元素  5.遍历list容器四、list容器的优缺点五、实际应用场景六、总结        本文将详细介绍C++STL中的list容器,包括其原理、常用......
  • 使用 setenv 配置文件管理 Tomcat 的自定义环境变量
    1、背景描述有时候,我们会在catalina.bat或catalina.sh文件中,自定义一些环境变量,例如额外指定JDK路径或设置JVM参数。实际上,直接在catalina.bat或catalina.sh文件中,自定义环境变量的做法,是不规范的。因为在对Tomcat进行(小版本)升级时,新版本的catalina.bat或cata......
  • HashMap 的长度为什么是2的幂次方?
    一、均匀分布哈希值当HashMap的长度是2的幂次方时,通过hashCode()计算出哈希值后,再与(length-1)进行与操作(例如index=hashCode()&(table.length-1)),可以使得哈希值更加均匀地分布在数组的下标范围内。假设哈希值是均匀分布的,那么与操作可以充分利用哈希值的各个位,......
  • .NET 8 Moq mock GetRequiredKeyedService Setup报错yk
    .NET8MoqmockGetRequiredKeyedServiceSetup报错项目代码里有地方用到IServiceProvider.GetRequiredKeyedService来解析服务,在写单元测试时需要Mock它,本以为像下面这样写就可以了:||varserviceProvider=newMock<IServiceProvider>();||---|---|||serviceP......