红黑树封装map和set超详解

 前言

                这篇博客完全是根据上篇博客红黑树来扩展的,代码的修改也是在红黑树那篇,大家可以先看看那篇代码再过来看看这篇更好食用哦!


目录

1.红黑树迭代器代码

2.红黑树的insert代码

3.map和set的封装

4.最后代码总和

5.最终测试


1.红黑树迭代器代码

1.1 RBTreeNod(红黑树结点)修改:

模板参数只需要一个即可,


enum Colour
{
	RED,
	BLACK
};

template
struct RBTreeNode
{
	RBTreeNode* _left;
	RBTreeNode* _right;
	RBTreeNode* _parent;

	T _date;//数据
	Colour _col;

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

1.2 __TreeIterator(封装map和set的迭代器)

(1) operator*   : 用来取出结点的数据,返回值&即可.

(2) operator-> :用来返回结点的地址, 用于map里访问pair里面的first 和 second.

(3) operator++ :

        迭代器++, 因为是二叉树的遍历++; 那么有下面两种情况; 请看图哦!

红黑树封装map和set超详解_第1张图片

可以发现(1)node结点的右子树是否为空; 如果不为空就是遍历到右子树的最左边结点;

(2)如果为空的话; 那么就说明这层子树以及遍历完了,我们需要回到祖父(parent的parent)去找另外一层子树的结点.

(4) operator--  :同样我们上图片看的更加明白;

红黑树封装map和set超详解_第2张图片可以发现: (1) node结点的左边结点是否存在,如果存在;那么就结点遍历到左子树的最右结点;

(2)如果node结点不存在的话,由于红黑树是二叉树,左子树不存在那么右子树更加不存在;

就代表这层树最左结点遍历完了,我们需要找到祖父结点去找.

(5)operator!= / operator== :  直接看一下代码就很快了解啦.


template
struct __TreeIterator
{
	typedef RBTreeNode Node;
	typedef __TreeIterator Self;
	Node* _node;

	__TreeIterator(Node* node)
		:_node(node)
	{}

	T& operator*()//解引用,取数据date的引用
	{
		return _node->_date;
	}

	T* operator->()//取数据date的地址,在解引用得到数据传回去.
	{
		return &_node->_date;
	}

	Self& operator--()//迭代器--
	{
		if (_node->_left)
		{
			Node* cur = _node->_left;
			while (cur->_right)
			{
				cur = cur->_right;
			}
			_node = cur;
		}
		else//左结点不存在的话那右结点也不会存在那么就要找祖父结点.
		{
			Node* parent = _node->_parent;
			Node* cur = _node;
			while (parent && cur == parent->_left)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			_node = cur;
		}
		return *this;
	}

	Self& operator--(int)//后置--
	{
		Self it(_node);
		--(*this);
		return it;
	}


	Self& operator++()//迭代器++
	{
		if (_node->_right)//结点的右子树存在,那么下一个结点一定是右子树的最左结点.
		{
			Node* cur = _node->_right;
			while (cur->_left)
			{
				cur = cur->_left;
			}
			_node = cur;
		}
		else//结点的右子树不存在,那么这颗树走完了,需要到孩子是父亲左的祖先.
		{
			Node* cur = _node;
			while (parent && cur ==  parent->_right)
			{
				cur = parent;
				parent = cur->_parent;
			}
			_node = cur;
		}
		return *this;
	}

	Self& operator++(int)//后置++
	{
		Self it(_node);
		++(*this);
		return it;
	}

	bool operator!=(const Self& s)
	{
		return _node != s._node;
	}

	bool operator==(const Self& s)
	{
		return _node == s._node;
	}
};

1.3  iterator以及const_iterator的begin和end

(1) begin是红黑树的最左边结点;

(2) end是由于结构要求就是设置为nullptr;

(3)const_iterator也是一样就是多了const,无法修改.

public:
	typedef __TreeIterator iterator;

	typedef __TreeIterator const_iterator;

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

	iterator 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);
	}

2.红黑树的insert代码

2.1红黑树找到插入位置

(1)返回值是pair, 返回迭代器和布尔参数.

(2)因为set和map是一起处理的, 那么传入数据模板统一都是T;

(3)KeyOfT是用来获取set和map中的key来进行比较的; 因为class是无法拿数据直接比较的.

如果插入相同的那么就是失败返回make_pair(iterator(cur), false).

(4)参数类型是const T& date.


    pair Insert(const T& date)
	{
		if (_root == nullptr)//结点为空
		{
			_root = new Node(date);
			_root->_col = BLACK;
			return make_pair(iterator(_root), true);
		}
		Node* parent = nullptr;
		Node* cur = _root;
		KeyOfT kot; //set和map数据kay的比较

		while (cur)//固定cur的位置
		{
			if (kot(cur->_date) < kot(date))//右边
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (kot(cur->_date) > kot(date))//左边
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return make_pair(iterator(cur), false);
			}
		}

		cur = new Node(date);
		Node* newnode = cur;
		cur->_col = RED;

		if (kot(parent->_date) < kot(date)//右边
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		else//左边
		{
			parent->_left = cur;
			cur->_parent = parent;
		}

		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			//    g
			//  p   u
			//c           
			if (parent == grandfather->_left)//父亲结点在祖父结点的左边;
			{
				Node* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_left)
					{    //    g
						//   p
						// c

						RotateR(grandfather);//直接右单旋
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//     g
						//   p
						//     c
						RotateL(parent);//先左单旋parent
						RotateR(grandfather);//在旋转grandfather
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
			else//父亲结点在祖父结点的右边;
			{
				//    g
				//  u   p
				//        c
				Node* uncle = grandfather->_left;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					//继续去上面结点处理
					cur = grandfather;
					parent = cur->_parent;
				}
				else//u结点是空或者黑色结点.
				{
					//   g
				   //  u   p
				   //        c
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//    g
						//  u   p
						//    c
						RotateR(parent);
						RotateL(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
		}

		_root->_col = BLACK;//根节点处理为黑.
		return make_pair(iterator(newnode), true);
	}

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

		parent->_right = subRL;
		subR->_left = parent;

		Node* parentParent = parent->_parent;

		parent->_parent = subR;
		if (subRL)
			subRL->_parent = parent;

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

			subR->_parent = parentParent;
		}
	}


	void RotateR(Node* parent)//对于第二种情况下左单旋和右单旋;
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

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

		Node* parentParent = parent->_parent;

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

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

			subL->_parent = parentParent;
		}
	}

2.2计算红黑树的高度

使用Height为了外面使用时候不用传递参数直接调用 _Height.

采用dfs递归的方法,遍历二叉搜索树.


    int Height()
	{
		return _Height(_root);
	}

	int _Height(Node* root)
	{
		if (root == nullptr)
			return 0;
		int leftHeight = _Height(_root->_left);
		int rightHeight = _Height(_root->_right);

		return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
	}

2.3计算红黑树的结点个数

也是采用递归方法,遍历二叉搜索树的左右结点.


    size_t Size()
	{
		return _Size(_root);
	}

	size_t _Size(Node* root)
	{
		if (root == nullptr)
			return 0;

		return _Size(root->_left)
			+ _Size(root->_right) + 1;
	}

2.4查找红黑树的数据

就是和找到插入数据结点的位置是一个逻辑.



	Node* find(const K& key)
	{
		Node* cur = _root;
		while (cur)
		{
			if (cur->_kv.first < key)
			{
				cur = cur->_right;
			}
			else if (cur->_kv.first > key)
			{
				cur = cur->_left;
			}
			else
			{
				return cur;
			}
		}
		return NULL;
	}

2.5检查红黑树

这部分上篇红黑树详解博客以及写的很清楚了,可以看看那篇.是一样的!

    void Inorder()
	{
		_Inorder(_root);
		cout << endl;
	}

	void _Inorder(Node* root)
	{
		if (root == nullptr)
			return;
		_Inorder(root->_left);
		cout << root->_kv.first << " ";
		_Inorder(root->_right);
	}

	bool check(Node* root, int blacknum, const int refVal)
	{
		if (root == nullptr)
		{
			if (blacknum != refVal)
			{
				cout << "存在黑色结点不相等的路径" << endl;
				return false;
			}
			return true;
		}


		//判断一黑一红
		if (root->_col == RED && root->_parent->_col == RED)
		{
			cout << "有连续的红色结点" << endl;
			return false;
		}

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

		return check(root->_left, blacknum, refVal) && check(root->_right, blacknum, refVal);
	}

	bool IsBalance()
	{
		if (_root == nullptr)
			return true;

		//检查根结点
		if (_root->_col == RED)
			return false;
		//参考值
		int refVal = 0;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_col == BLACK)
			{
				refVal++;
			}
			cur = cur->_left;
		}

		//检查一黑一红//检查黑色结点数量
		int blacknum = 0;
		return check(_root, 0, refVal);
	}

3.map和set的封装

3.1set的封装

(1) SetKeyofT是用来operator(); 因为在比较数据时候得拿出来key那么必须封装起来;直接去取是拿不到的.


namespace study
{
	template
	class set
	{
	public:
		struct SetKeyofT//在进行比较数据的时候需要用到
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};


		//+typename是因为对模板取内嵌类型需要+typename告诉编译器是类型
		typedef  RBTree::iterator iterator;
		typedef  RBTree::const_iterator const_iterator;
		
		iterator begin()const
		{
			return _t.begin();
		}

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

		pair insert(const K& key)
		{
			return _t.Insert(key);
		}
	private:
		RBTree _t;
	};
}

3.2map的封装

(1) MapKeyofT也是和set一样的;

(2) 因为map的参数里面有key和value;所以还是和set有不同; operator()是取出kv的first;

(3) 相比set还有多了一个operator[];

pair ret = insert(make_pair(key, V()));

这里插入数据make_pair(key, V());  V()是匿名对象.返回值就是pair.


namespace study
{
	template
	class map
	{
	public:
		struct MapKeyOfT
		{
			const K& operator()(const pair& kv)
			{
				return kv.first;
			}
		};


		typedef typename RBTree, MapKeyOfT>::iterator iterator;
		typedef typename RBTree, MapKeyOfT>::const_iterator const_iterator;
		
		iterator begin()
		{
			return _t.begin();
		}

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

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

		pair insert(const pair& kv)
		{
			return _t.Insert(kv);
		}
	private:
		RBTree, MapKeyOfT> _t;
	};
}

4.最后代码总和

将代码分成这几个.h / .cpp文件;

4.1RBTree

#pragma once
#include
using namespace std;
enum Colour
{
	RED,
	BLACK
};

template
struct RBTreeNode
{
	RBTreeNode* _left;
	RBTreeNode* _right;
	RBTreeNode* _parent;

	T _date;//数据
	Colour _col;

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

template
struct __TreeIterator
{
	typedef RBTreeNode Node;
	typedef __TreeIterator Self;
	Node* _node;

	__TreeIterator(Node* node)
		:_node(node)
	{}

	Ref operator*()//解引用,取数据date的引用
	{
		return _node->_date;
	}

	Ptr operator->()//取数据date的地址,在解引用得到数据传回去.
	{
		return &_node->_date;
	}

	Self& operator--()//迭代器--
	{
		if (_node->_left)
		{
			Node* cur = _node->_left;
			while (cur->_right)
			{
				cur = cur->_right;
			}
			_node = cur;
		}
		else//左结点不存在的话那右结点也不会存在那么就要找祖父结点.
		{
			Node* parent = _node->_parent;
			Node* cur = _node;
			while (parent && cur == parent->_left)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			_node = cur;
		}
		return *this;
	}

	Self& operator--(int)//后置--
	{
		Self it(_node);
		--(*this);
		return it;
	}


	Self& operator++()//迭代器++
	{
		if (_node->_right)//结点的右子树存在,那么下一个结点一定是右子树的最左结点.
		{
			Node* cur = _node->_right;
			while (cur->_left)
			{
				cur = cur->_left;
			}
			_node = cur;
		}
		else//结点的右子树不存在,那么这颗树走完了,需要到孩子是父亲左的祖先.
		{
			Node* cur = _node;
			Node* parent = cur->_parent;
			while (parent && cur ==  parent->_right)
			{
				cur = parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}

	Self& operator++(int)//后置++
	{
		Self it(_node);
		++(*this);
		return it;
	}

	bool operator!=(const Self& s)
	{
		return _node != s._node;
	}

	bool operator==(const Self& s)
	{
		return _node == s._node;
	}
};

template
class RBTree
{
	typedef RBTreeNode Node;

public:
	typedef __TreeIterator iterator;

	typedef __TreeIterator const_iterator;

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

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

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

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


	//pair Insert(const T& date)
	pair Insert(const T& date)
	{
		if (_root == nullptr)//结点为空
		{
			_root = new Node(date);
			_root->_col = BLACK;
			return make_pair(_root, true);
		}
		Node* parent = nullptr;
		Node* cur = _root;
		KeyofT kot; //取出set和map数据key的进行比较;

		while (cur)//固定cur的位置
		{
			if (kot(cur->_date) < kot(date))//右边
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (kot(cur->_date) > kot(date))//左边
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return make_pair(cur, false);
			}
		}

		cur = new Node(date);
		Node* newnode = cur;
		cur->_col = RED;

		if (kot(parent->_date) < kot(date))//右边
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		else//左边
		{
			parent->_left = cur;
			cur->_parent = parent;
		}

		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			//    g
			//  p   u
			//c           
			if (parent == grandfather->_left)//父亲结点在祖父结点的左边;
			{
				Node* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_left)
					{    //    g
						//   p
						// c

						RotateR(grandfather);//直接右单旋
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//     g
						//   p
						//     c
						RotateL(parent);//先左单旋parent
						RotateR(grandfather);//在旋转grandfather
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
			else//父亲结点在祖父结点的右边;
			{
				//    g
				//  u   p
				//        c
				Node* uncle = grandfather->_left;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					//继续去上面结点处理
					cur = grandfather;
					parent = cur->_parent;
				}
				else//u结点是空或者黑色结点.
				{
					//   g
				   //  u   p
				   //        c
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//    g
						//  u   p
						//    c
						RotateR(parent);
						RotateL(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
		}

		_root->_col = BLACK;//根节点处理为黑.
		return make_pair(newnode, true);
	}

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

		parent->_right = subRL;
		subR->_left = parent;

		Node* parentParent = parent->_parent;

		parent->_parent = subR;
		if (subRL)
			subRL->_parent = parent;

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

			subR->_parent = parentParent;
		}
	}


	void RotateR(Node* parent)//对于第二种情况下左单旋和右单旋;
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

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

		Node* parentParent = parent->_parent;

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

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

			subL->_parent = parentParent;
		}
	}

	void Inorder()
	{
		_Inorder(_root);
		cout << endl;
	}

	void _Inorder(Node* root)
	{
		if (root == nullptr)
			return;
		_Inorder(root->_left);
		cout << root->_kv.first << " ";
		_Inorder(root->_right);
	}

	bool check(Node* root, int blacknum, const int refVal)
	{
		if (root == nullptr)
		{
			if (blacknum != refVal)
			{
				cout << "存在黑色结点不相等的路径" << endl;
				return false;
			}
			return true;
		}


		//判断一黑一红
		if (root->_col == RED && root->_parent->_col == RED)
		{
			cout << "有连续的红色结点" << endl;
			return false;
		}

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

		return check(root->_left, blacknum, refVal) && check(root->_right, blacknum, refVal);
	}

	bool IsBalance()
	{
		if (_root == nullptr)
			return true;

		//检查根结点
		if (_root->_col == RED)
			return false;
		//参考值
		int refVal = 0;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_col == BLACK)
			{
				refVal++;
			}
			cur = cur->_left;
		}

		//检查一黑一红//检查黑色结点数量
		int blacknum = 0;
		return check(_root, 0, refVal);
	}

	int Height()
	{
		return _Height(_root);
	}

	int _Height(Node* root)
	{
		if (root == nullptr)
			return 0;
		int leftHeight = _Height(_root->_left);
		int rightHeight = _Height(_root->_right);

		return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
	}

	size_t Size()
	{
		return _Size(_root);
	}

	size_t _Size(Node* root)
	{
		if (root == nullptr)
			return 0;

		return _Size(root->_left)
			+ _Size(root->_right) + 1;
	}

	Node* Find(const K& key)
	{
		Node* cur = _root;
		while (cur)
		{
			if (cur->_kv.first < key)
			{
				cur = cur->_right;
			}
			else if (cur->_kv.first > key)
			{
				cur = cur->_left;
			}
			else
			{
				return cur;
			}
		}
		return NULL;
	}
private:
	Node* _root = nullptr;
};

4.2 Myset

#pragma once
#include"RBTree.h"

namespace study
{
	template
	class set
	{
	public:
		struct SetKeyofT//在进行比较数据的时候需要用到
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};


		//+typename是因为对模板取内嵌类型需要+typename告诉编译器是类型
		typedef typename RBTree::const_iterator iterator;
		typedef typename RBTree::const_iterator const_iterator;
		
		iterator begin()const
		{
			return _t.begin();
		}

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

		pair insert(const K& key)
		{
			return _t.Insert(key);
		}
	private:
		RBTree _t;
	};
}

4.3 Mymap

#pragma once
#include"RBTree.h"

namespace study
{
	template
	class map
	{
	public:
		struct MapKeyOfT
		{
			const K& operator()(const pair& kv)
			{
				return kv.first;
			}
		};


		typedef typename RBTree, MapKeyOfT>::iterator iterator;
		typedef typename RBTree, MapKeyOfT>::const_iterator const_iterator;
		
		iterator begin()
		{
			return _t.begin();
		}

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

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

		pair insert(const pair& kv)
		{
			return _t.Insert(kv);
		}
	private:
		RBTree, MapKeyOfT> _t;
	};
}

5.最终测试

test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include
using namespace std;

#include"RBTree.h"
#include"Mymap.h"
#include"Myset.h"

void test_set()
{
	study::set s;
	s.insert(4);
	s.insert(1);
	s.insert(2);
	s.insert(3);
	s.insert(2);
	s.insert(0);
	s.insert(10);
	s.insert(5);

	study::set::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << endl;
		it++;
	}
	cout << endl;

	it = s.begin();
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
}

void test_map()
{
	study::map dict;
	dict.insert(make_pair("sort", ""));
	dict.insert(make_pair("sort", "xx"));
	dict.insert(make_pair("left", ""));
	dict.insert(make_pair("right", "yy"));

	//study::map::iterator it1 = dict.begin();
	//while (it1 != dict.end())
	//{
	//	// key޸
	//	//it->first += 'x';
	//	//it1->second += 'y';

	//	cout << it1->first << ":" << it1->second << endl;
	//	++it1;
	//}
	//cout << endl;

	string arr[] = { "哈密瓜", "香蕉","火龙果", "香蕉", "香蕉", "火龙果"};
	study::map countMap;
	for (auto& e : arr)
	{
		countMap[e]++;
	}

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


int main()
{
	test_set();
	test_map();
	return 0;
}

红黑树封装map和set超详解_第3张图片xdm,这篇写了整整两天,看博主这么肝,给个三连不过分吧!!!

你可能感兴趣的:(c++专栏,c++,数据结构)