map和set

set和map
1.关联式容器

在之前,我们已经接触过STL容器中的部分容器(vector、list、deque、forward_ list),这些容器我们称为序列式容器。因为其底层是线性的数据结构,里面存储的是元素本身。

关联式容器也是用来存储数据的,与序列式容器不同的是,里面存储的是<key,value>结构的键值对,在数据索引时比序列式容器效率更高。

2.键值对

用来表示具有一一对应关系的一种结构,该结构中一般只有两个成员变量key和value。key代表键值,value表示与key对应的信息。

在STL中关于键值对的定义如下:

template <class K, class V>
struct pair
{
	K first;
	V second;
	pair()
		:first(K())
		,second(V())
	{}
	pair(const K& a, cosnt V& b)
		:first(a)
		, second(b)
	{}
};
3.set
3.1set的介绍

a.set是按照一定次序存储元素的容器

b.在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。

c.在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。

d.set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。

e.set在底层是用二叉搜索树(红黑树)实现的。

3.2set的构造
int main()
{
	set<int> s1;
	set<int> s2{ 1,2,3,4,5,6 };
	set<int> s3(s2);
}
3.3set的迭代器
int main()
{
	set<int> s{ 1,2,3,4,5,6 };
    //正向迭代器
	set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << endl;
		it++;
	}
	//const迭代器
	set<int>::const_iterator cit = s.cbegin();
	while (cit != s.cend())
	{
		cout << *cit << endl;
		cit++;
	}
    //反向迭代器
	set<int>::reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
		cout << *rit << endl;
		rit++;
	}
	return 0;
}
3.4set的修改操作
int main()
{
	set<int> s;
    //插入操作
	s.insert(1);
	s.insert(4);
	s.insert(2);
	s.insert(5);
    //删除值为1的元素
	s.erase(1);
    //有效元素个数
	s.size();
    //查找值为4的元素
	set<int>::iterator ret = s.find(4);
	cout << *ret << endl;
    //清空集合
	s.clear();
    //判空操作
	s.empty();
	return 0;
}
3.5multiset

a.multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。

b.在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成的键值对,因此value本身就是key,key就是value,类型为T). multiset元素的值不能在容器中进行修改(因为元素总是const的),但可以从容器中插入或删除。

c.在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序。

d.multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时会得到一个有序序列。

e.multiset底层结构为二叉搜索树(红黑树)。

4.map
4.1map的介绍

a.map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素

b.在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair:typedef pair value_type;

c.在内部,map中的元素总是按照键值key进行比较排序的。

d.map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。

e.map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。

f.map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

4.2map的构造
int main()
{
    //构造空的map
	map<int, int> m;
	return 0;
}
4.3map的迭代器
int main()
{
	map<int, int> m;
	m.insert(make_pair(1, 12));
	m.insert(make_pair(2, 12));
	m.insert(make_pair(3, 15));
	m.insert(make_pair(4, 102));
	//正向迭代器
	map<int, int>::iterator it = m.begin();
	while (it != m.end())
	{
		cout << it->first << ":" << it->second << endl;
		it++;
	}
	cout << endl;
    //const迭代器
	map<int, int>::const_iterator cit = m.cbegin();
	while (cit != m.cend())
	{
		cout << cit->first << ":" << cit->second << endl;
		cit++;
	}
	cout << endl;
    //反向迭代器
	map<int, int>::reverse_iterator rit = m.rbegin();
	while (rit != m.rend())
	{
		cout << rit->first << ":" << rit->second << endl;
		rit++;
	}
	cout << endl;
	return 0;
}
4.4map的修改操作
int main()
{
	map<int, int> m;
    //自己显示定义pair插入
	m.insert(pair<int, int>(1, 12));
	m.insert(pair<int, int>(2, 12));
    //使用make_pair函数插入
	m.insert(make_pair(3, 15));
	m.insert(make_pair(4, 102));
    //删除key值为1的元素
	m.erase(1);
    //有效元素个数
	m.size();
    //查找key值为4的元素
	map<int, int>::iterator ret = m.find(4);
	cout << ret->first << ":" << ret->second << endl;
    //清空集合
	m.clear();
    //判空操作
	m.empty();
	return 0;
}
4.5multimap

a.Multimaps是关联式容器,它按照特定的顺序,存储由key和value映射成的键值对<key, value>,其中多个键值对之间的key是可以重复的。

b.在multimap中,通常按照key排序和惟一地标识元素,而映射的value存储与key关联的内容。key和value的类型可能不同,通过multimap内部的成员类型value_type组合在一起,value_type是组合key和value的键值对:typedef pair<const Key, T> value_type。

c.在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对key进行排序的。

d.multimap通过key访问单个元素的速度通常比unordered_multimap容器慢,但是使用迭代器直接遍历multimap中的元素可以得到关于key有序的序列。

e.multimap在底层用二叉搜索树(红黑树)来实现。

5.红黑树模拟实现set和map
5.1对红黑树进行改造且生成迭代器
#pragma once

#include<iostream>
#include<map>
using namespace std;
enum Colour
{
	RED,
	BLACK,
};

template<class T>
struct RBTreeNode
{
	RBTreeNode(T& data)
		:_data(data)
		, _left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _col(RED)
	{}
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
	T _data;
	Colour _col;
};

template<class T>
struct _TreeIterator
{
	typedef RBTreeNode<T> Node;
	typedef _TreeIterator<T> Self;
	Node* _node;

	_TreeIterator(Node* node)
		:_node(node)
	{}
	T& operator*()
	{
		return _node->_data;
	}

	T* operator->()
	{
		return &_node->_data;
	}

	Self& operator++()
	{
		if (_node->_right)
		{
			Node* subleft = _node->_right;
			while (subleft->_left)
			{
				subleft = subleft->_left;
			}
			_node = subleft;
		}
		else
		{
			Node* cur = _node;
			Node* parent = cur->_parent;
			while (parent && parent->_right == cur)
			{
				cur = parent;
				parent = cur->_parent;
			}
			_node = parent;
		}
		return *this;
	}
	Self& operator--()
	{
		if (_node->_left)
		{
			Node* subright = _node->_left;
			while (subright->_right)
			{
				subright = subright->_right;
			}
			_node = subright;
		}
		else
		{
			Node* cur = _node;
			Node* parent = cur->_parent;
			while (parent && parent->_left == cur)
			{
				cur = parent;
				parent = cur->_parent;
			}
			_node = parent;
		}
		return *this;
	}

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

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

template<class K, class T, class KofT>
class RBTree
{
public:
	typedef RBTreeNode<T> Node;
	typedef _TreeIterator<T> iterator;
	iterator begin()
	{
		Node* cur = _root;
		while (cur && cur->_left)
		{
			cur = cur->_left;
		}
		return iterator(cur);
	}
	iterator end()
	{
		return iterator(nullptr);
	}
	pair<iterator, bool> Insert(T data)
	{
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return make_pair(iterator(_root), true);
		}
		KofT koft;
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (koft(cur->_data) > koft(data))
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (koft(cur->_data) < koft(data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return make_pair(iterator(cur), false);
			}
		}
		cur = new Node(data);
		Node* newnode = cur;
		if (koft(parent->_data) > koft(data))
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		cur->_col = RED;
		while (parent && parent->_col == RED)
		{
			Node* grandfther = parent->_parent;
			if (grandfther->_left == parent)
			{
				Node* uncle = grandfther->_right;
				if (uncle && uncle->_col == RED)
				{
					grandfther->_col = RED;
					parent->_col = uncle->_col = BLACK;

					parent = grandfther->_parent;
					cur = grandfther;
				}
				else
				{
					if (cur == parent->_right)
					{
						RotateL(parent);
						swap(parent, cur);
					}
					RotateR(grandfther);
					grandfther->_col = RED;
					parent->_col = BLACK;
					break;
				}
			}
			else
			{
				Node* uncle = grandfther->_left;
				if (uncle && uncle->_col == RED)
				{
					grandfther->_col = RED;
					parent->_col = uncle->_col = BLACK;

					parent = grandfther->_parent;
					cur = grandfther;
				}
				else
				{
					if (cur == parent->_left)
					{
						RotateR(parent);
						::swap(parent, cur);
					}
					RotateL(grandfther);
					grandfther->_col = RED;
					parent->_col = BLACK;
					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;
		if (subRL)
			subRL->_parent = parent;

		subR->_left = parent;
		Node* ppNode = parent->_parent;
		parent->_parent = subR;

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

			subR->_parent = ppNode;
		}
	}

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

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

		subL->_right = parent;
		Node* ppNode = parent->_parent;
		parent->_parent = subL;

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

			subL->_parent = ppNode;
		}
	}

	iterator Find(const K& key)
	{
		KofT koft;
		Node* cur = _root;
		while (cur)
		{
			if (koft(cur->_data) > key)
				cur = cur->_left;
			else if (cur->_kv.first < key)
				cur = cur->_right;
			else
				return iterator(cur);
		}
		return iterator(nullptr);
	}
private:
	Node* _root = nullptr;
};
5.2set的模拟实现
#pragma once

#include"RBTree.h"
namespace Set
{
	template<class K>
	class set
	{
		struct SetKetOfT
		{
			const K& operator()(const K& k)
			{
				return k;
			}
		};
	public:
		typedef typename RBTree<K, K, SetKetOfT>::iterator iterator;
		
		iterator begin()
		{
			return _t.begin();
		}
		iterator end()
		{
			return _t.end();
		}
		pair<iterator, bool> Insert(const K& k)
		{
			return _t.Insert(k);
		}
	private:
		RBTree<K, K, SetKetOfT> _t;
	};
}
5.3map的模拟实现
#pragma once
#include "RBTree.h"
#include<string>
namespace Map
{
	template<class K, class V>
	class map
	{
		struct MapKeyOfT
		{
			const K& operator()(const pair<K, V> & kv)
			{
				return kv.first;
			}
		};
	public:
		typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;
		iterator begin()
		{
			return _t.begin();
		}
		iterator end()
		{
			return _t.end();
		}
		pair<iterator, bool> Insert(const pair<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<K, V>, MapKeyOfT> _t;
	};
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值