总的来说set和map是关联式容器,而我们前面学习的vector和list的序列式容器。

    set和map底层几乎是搜索二叉树,所以他们都可以进行排序和去重,走的是中序遍历


1、set(底层相当于key的搜索树)

set与map_中序遍历

具体可以看:https://legacy.cplusplus.com/reference/set/set/?kw=set

a、插入:

set与map_二叉搜索树_02

b、删除:

set与map_中序遍历_03

set与map_中序遍历_04

注:

set与map_二叉搜索树_05

2、multiset:

    multiset与set的区别是multiset可以有重复的元素。

namespace k
{
	template<class k>
	//控制节点
	struct BSTNode
	{
		k _key;
		BSTNode<k>* _left;
		BSTNode<k>* _right;

		//构造
		BSTNode(const k& key)
			:_key(key)
			, _left(nullptr)
			, _right(nullptr)
		{}
	};

	template<class k>
	//控制二叉搜索树
	class BST
	{
		typedef BSTNode<k> Node;
	public:
		BSTree() = default;

		BSTree(const k& t)
		{
			_root = Copy(t._root);
		}

		~BSTree()
		{
			Destroy(_root);
			_root = nullptr;
		}

		//查找函数
		bool find(const k& key)
		{
			Node* cur = _root;
			while (cur)
			{
				if (cur->_key < key)
				{
					cur = cur->_right;
				}
				else if (cur->_key > key)
				{
					cur = cur->_left;
				}
				else
				{
					return true;
				}
			}
			return false;
		}

		//插入函数
		bool insert(const k& key)
		{
			if (_root == nullptr)
			{
				_root = new Node(key);
				return true;
			}

			Node* cur = _root;
			Node* parent = nullptr;
			while (cur)
			{
				if (cur->_key < key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (cur->_key > key)
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return false;
				}
			}

			cur = new Node(key);
			if (parent->_key < key)
			{
				parent->_right = cur;
			}
			else
			{
				parent->_left = cur;
			}

			return true;
		}

		//删除函数(用改值来做到删除)
		//分为(1)叶子和一个孩子(2)两个孩子
		bool erase(const k& key)
		{
			Node* cur = _root;
			Node* parent = nullptr;
			while (cur)
			{
				if (cur->_key < key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (cur->_key > key)
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					//0或1个孩子
					//只有右孩子
					if (cur->_left == nullptr)
					{
						//cur为根节点
						if (parent == nullptr)
						{
							_root = cur->_right;
						}
						else
						{
							if (parent->_left == cur)
							{
								parent->_left = cur->_right;
							}
							else
								parent->_right = cur->_right;
						}
						delete cur;
						return true;
					}
					//只有左孩子
					else if (cur->_right == nullptr)
					{
						//cur为根节点
						if (parent == nullptr)
						{
							_root = cur->_left;
						}
						else
						{
							if (parent->_left == cur)
							{
								parent->_left = cur->_left;
							}
							else
								parent->_right = cur->_left;
						}
						delete cur;
						return true;
					}
					//有两个孩子
					//找替代节点,右最小或左最大(满足二叉搜索树要求)
					//左最大
					else
					{
						Node* leftmax = cur->_left;
						Node* leftmaxp = cur;
						//左子树的最右边为最大
						while (leftmax->_right)
						{
							leftmaxp = leftmax;
							leftmax = leftmax->_right;
						}

						cur->_key = leftmax->_key;
						if (leftmaxp->_left == leftmax)
						{
							leftmaxp->_left = leftmax->_left;
						}
						else
							leftmaxp->_right = leftmax->_left;
						delete leftmax;
						return true;
					}
					//右最小
					//else
					//{
					//	Node* rightmin = cur->_right;
					//	Node* rightminp = cur;
					//	//右子树的最左边为最小
					//	while (rightmin->_left)
					//	{
					//		rightminp = rightmin;
					//		rightmin = rightmin->_left;
					//	}

					//	cur->_key = rightmin->_key;
					//	if (rightminp->_left == rightmin)
					//	{
					//		rightminp->_left = rightmin->_right;
					//	}
					//	else
					//		rightminp->_right = rightmin->_right;
					//	delete rightmin;
					//	return true;
					//	}
				}
			}
		}

		//中序遍历
		void Inorder()
		{
			_Inorder(_root);
			cout << endl;
		}
	private:
		//若将该函数放在外边无法访问root
		void _Inorder(Node* root)
		{
			if (root == nullptr)
			{
				return;
			}
			_Inorder(root->_left);
			cout << root->_key << " ";
			_Inorder(root->_right);
		}
		void Destroy(Node* root)
		{
			if (root == nullptr)
				return;

			Destroy(root->_left);
			Destroy(root->_right);
			delete root;
		}

		Node* Copy(Node* root)
		{
			if (root == nullptr)
				return nullptr;

			Node* newRoot = new Node(root->_key, root->_value);
			newRoot->_left = Copy(root->_left);
			newRoot->_right = Copy(root->_right);

			return newRoot;
		}

		Node* _root = nullptr;
	};
}

3、map(适用于一个值找另一个值)

https://legacy.cplusplus.com/reference/map/map/?kw=map

set与map_中序遍历_06

map可以通过key和value这对键对值实现部分操作。

template<class K, class V>
struct BSTNode
{
	// pair<K, V> _kv;
	K _key;
	V _value;
	BSTNode<K, V>* _left;
	BSTNode<K, V>* _right;

	BSTNode(const K& key, const V& value)
		:_key(key)
		, _value(value)
		, _left(nullptr)
		, _right(nullptr)
	{}
};

template<class K, class V>
class BSTree
{
	typedef BSTNode<K, V> Node;
public:
	BSTree() = default;

	BSTree(const BSTree<K, V>& t)
	{
		_root = Copy(t._root);
	}

	~BSTree()
	{
		Destroy(_root);
		_root = nullptr;
	}

	bool Insert(const K& key, const V& value)
	{
		if (_root == nullptr)
		{
			_root = new Node(key, value);
			return true;
		}

		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}

		cur = new Node(key, value);
		if (parent->_key < key)
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}

		return true;
	}

	Node* Find(const K& key)
	{
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key < key)
			{
				cur = cur->_right;
			}
			else if (cur->_key > key)
			{
				cur = cur->_left;
			}
			else
			{
				return cur;
			}
		}

		return nullptr;
	}

	bool Erase(const K& key)
	{
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				// 删除
				// 0-1个孩子的情况
				if (cur->_left == nullptr)
				{
					if (parent == nullptr)
					{
						_root = cur->_right;
					}
					else
					{
						if (parent->_left == cur)
							parent->_left = cur->_right;
						else
							parent->_right = cur->_right;
					}

					delete cur;
					return true;
				}
				else if (cur->_right == nullptr)
				{
					if (parent == nullptr)
					{
						_root = cur->_left;
					}
					else
					{
						if (parent->_left == cur)
							parent->_left = cur->_left;
						else
							parent->_right = cur->_left;
					}

					delete cur;
					return true;
				}
				else
				{
					// 2个孩子的情况
					// 右子树的最小节点作为替代节点
					Node* rightMinP = cur;
					Node* rightMin = cur->_right;
					while (rightMin->_left)
					{
						rightMinP = rightMin;
						rightMin = rightMin->_left;
					}

					cur->_key = rightMin->_key;

					if (rightMinP->_left == rightMin)
						rightMinP->_left = rightMin->_right;
					else
						rightMinP->_right = rightMin->_right;

					delete rightMin;
					return true;
				}
			}
		}

		return false;
	}

	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}
private:
	void _InOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}

		_InOrder(root->_left);
		cout << root->_key << ":" << root->_value << endl;
		_InOrder(root->_right);
	}

	void Destroy(Node* root)
	{
		if (root == nullptr)
			return;

		Destroy(root->_left);
		Destroy(root->_right);
		delete root;
	}

	Node* Copy(Node* root)
	{
		if (root == nullptr)
			return nullptr;

		Node* newRoot = new Node(root->_key, root->_value);
		newRoot->_left = Copy(root->_left);
		newRoot->_right = Copy(root->_right);

		return newRoot;
	}

private:
	Node* _root = nullptr;
};

map中的operator[]

   其底层是用插入函数实现的,而insert函数含有的值有两个,一个是所含的值,另一个是bool类型,若map中没改值则插入成功为true,若有则插入失败为false,其返回值是相关的迭代器。

set与map_子树_07

4、multimap

set与map_二叉搜索树_08