首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

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

编程知识
2024年08月31日 19:55

改造红黑树

目录

在初次看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;
	}
	}
}



From:https://www.cnblogs.com/DSCL-ing/p/18390555
本文地址: http://shuzixingkong.net/article/1620
0评论
提交 加载更多评论
其他文章 C++ lambda 引用捕获临时对象引发 coredump 的案例
今天复习前几年在项目过程中积累的各类技术案例,有一个小的 coredump 案例,当时小组里几位较资深的同事都没看出来,后面是我周末查了两三个小时解决掉的,今天再做一次系统的总结,给出一个复现的案例代码,案例代码比较简单,便于学习理解。 1. 简介 原则:临时对象不应该被 lambda 引用捕获,因
C++ lambda 引用捕获临时对象引发 coredump 的案例
SNAT 与 DNAT
本文为博主原创,转载请注明出处: SNAT(Source Network Address Translation,源网络地址转换)和DNAT(Destination Network Address Translation,目标网络地址转换)是网络地址转换(NAT)中的两种重要技术,它们在实现内部网络
[postgres]使用pgbench进行基准测试
前言 pgbench是一种在postgres上进行基准测试的简单程序,一般安装后就会自带。pgbench可以再并发的数据库绘画中一遍遍地进行相同序列的SQL语句,并且计算平均事务率。 测试准备 既然要测postgres,肯定要先有个postgres。安装过程略过。 一些环境信息: postgres版
Go plan9 汇编: 打通应用到底层的任督二脉
原创文章,欢迎转载,转载请注明出处,谢谢。 0. 前言 作为一个严肃的 Gopher,了解汇编是必须的。本汇编系列文章会围绕基本的 Go 程序介绍汇编的基础知识。 1. Go 程序到汇编 首先看一个简单到令人发指的示例: package main func main() { a := 1 print
Go plan9 汇编: 打通应用到底层的任督二脉 Go plan9 汇编: 打通应用到底层的任督二脉
大请求、请求超时问题
耗时很长的请求怎么处理?比如数据量大的。业务逻辑处理时间太久,以至于响应超时 这里的超时响应指的是ReadTimeOut,即发送请求内容完毕到接收响应数据开始的这段时间。普通HTTP请求可能在这段时间没有响应超时。 HTTP分块传输(Chunked Transfer Encoding)中每个数据块的
大请求、请求超时问题 大请求、请求超时问题 大请求、请求超时问题
全网最适合入门的面向对象编程教程:42 Python常用复合数据类型-collections容器数据类型
在Python中,collections模块提供了一组高效、功能强大的容器数据类型,扩展了内置的基础数据类型(如list、tuple、dict等),这些容器数据类型在处理特定问题时,能够提供更简洁、更高效的解决方案。
全网最适合入门的面向对象编程教程:42 Python常用复合数据类型-collections容器数据类型 全网最适合入门的面向对象编程教程:42 Python常用复合数据类型-collections容器数据类型 全网最适合入门的面向对象编程教程:42 Python常用复合数据类型-collections容器数据类型
喜报!Fluent Editor 开源富文本迎来了第一位贡献者!
你好,我是 Kagol,个人公众号:前端开源星球。 2024年8月20日,刚开源一周的富文本 Fluent Editor 迎来了第一位贡献者:zzxming,带大家一起分析下这个 #10 这个PR。
喜报!Fluent Editor 开源富文本迎来了第一位贡献者! 喜报!Fluent Editor 开源富文本迎来了第一位贡献者! 喜报!Fluent Editor 开源富文本迎来了第一位贡献者!
MySQL的索引原理及使用
B+树的最底层叶子节点包含了所有的索引项。从图上可以看到,B+树在查找数据的时候,由于数据都存放在最底层的叶子节点上,所以每次查找都需要检索到叶子节点才能查询到数据。所以在需要查询数据的情况下每次的磁盘的IO跟树高有直接的关系,但是从另一方面来说,由于数据都被放到了叶子节点,
MySQL的索引原理及使用 MySQL的索引原理及使用 MySQL的索引原理及使用