1.Map和Set的简单介绍
Map和set没有多大区别,它俩都是键值对容器,即该结构中一般只包含两个成员key,value,key代表键值,value表示与key对应的信息。并且这两个容器为树型结构的关联式容器,这两种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。
Set的介绍:
- set是按照一定次序存储元素的容器。
- 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。
- set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
- 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。
- set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。
- set在底层是用二叉搜索树(红黑树)实现的。
注意:
- 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。
- set中插入元素时,只需要插入value即可,不需要构造键值对。
- set中的元素不可以重复(因此可以使用set进行去重)。
- 使用set的迭代器遍历set中的元素,可以得到有序序列
- set中的元素默认按照小于来比较
- set中查找某个元素,时间复杂度为:$log_2 n$
- set中的元素不允许修改
- set中的底层使用二叉搜索树(红黑树)来实现
Map的介绍:
- map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。
- 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型
- value_type绑定在一起,为其取别名称为pair:
- typedef pair<const key, T> value_type;
- 在内部,map中的元素总是按照键值key进行比较排序的。
- map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
- map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
- map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。
2.Map和Set的实现
由于Map和Set的底层都为红黑树,所以Map和Set的实现通过对红黑树的封装来实现,Set为一个参数,Map为两个参数,所以通过改变模板来实现Map和Set的同时封装。
Set的简单封装:
namespace sss
{template<class K>class Set{struct SetKeyofT{const K& operator()(const K& date){return date;}}; public:typedef typename RedBlackTree<K, K, SetKeyofT>::iterator iterator;iterator begin(){return _S.begin();}iterator end(){return _S.end();}pair<iterator, bool> Insert(const K& date){return _S.insert(date);}private:RedBlackTree<K, K, SetKeyofT> _S;};//测试用例/*void text_set(){string str[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };Set<string> hash;for (auto sh : str){hash.Insert(sh);}auto it = hash.begin();while (it != hash.end()){cout << *it << endl;++it;}}*/}
Map的简单封装
namespace sss
{template<class K,class V> class Map{public:struct MapKeyofT{const K& operator()(const pair<K, V>& date){return date.first;}};typedef typename RedBlackTree<K, pair<K, V>, MapKeyofT>::iterator iterator;//t//ypedef RedBlackTree<K, pair<K, V>, MapKeyofT> RedBlackTree;iterator begin() {return _T.begin();}iterator end(){return _T.end();}pair<iterator, bool> Insert(const pair<K,V>& date){return _T.insert(date);}V& operator[](const K& key){pair<iterator, bool> ret = Insert(make_pair(key, V()));return ret.first->second;}private:RedBlackTree<K,pair<K,V>, MapKeyofT> _T;};//测试用例//void text_map()//{// Map<int, int> hash1;// hash1.Insert(make_pair(1,1));// cout<<hash1[1];// Map<string, int> hash2;// string str[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };// for (auto sh:str)// {// hash2[sh]++;// }// Map<string, int>::iterator it = hash2.begin();// while (it != hash2.end())// {// cout << it->first << ":" << it->second << endl;// ++it;// }// for (auto& kv : hash2)// {// cout << kv.first << ":" << kv.second << endl;// }// //hash1 = hash2;// //}
}
底层实现:
namespace sss
{enum Color{red,black};template<class T>struct RedBlackTreeNode{RedBlackTreeNode<T>* _left;RedBlackTreeNode<T>* _right;RedBlackTreeNode<T>* _parent;//pair<K, V> _date;T _date;Color _col;RedBlackTreeNode(const T& date=T()):_left(nullptr),_right(nullptr),_parent(nullptr),_date(date)//, _col(black){}};template<class T, class Ref, class Ptr>struct __RBTreeIterator{typedef RedBlackTreeNode<T> Node;typedef __RBTreeIterator<T, Ref, Ptr> Self;Node* _node;__RBTreeIterator(Node* node):_node(node){}Ref operator*(){return _node->_date;}Ptr operator->(){return &_node->_date;}bool operator!=(const Self& _t){return _node != _t._node;}bool operator==(const Self& _t){return _node == _t._node;}Self* operator++(){if (_node->_right){Node* cur = _node;cur = cur->_right;while (cur->_left){cur = cur->_left;}_node=cur;}else{Node* parent = _node->_parent;Node* cur = _node;while (parent && cur == parent->_right){cur = cur->_parent;parent = parent->_parent;}_node=parent;}return this;}Self* operator--(){if (_node->_left){Node* cur = _node;cur = cur->_left;while (cur->_right){cur = cur->_right;}_node=cur;}else{Node* parent = _node->_parent;Node* cur = _node;while (parent && cur == parent->left){parent = parent->_parent;cur = parent;}_node= parent;}return this;}};template<class K, class T, class KeyofT>class RedBlackTree{typedef RedBlackTreeNode<T> Node;public: typedef __RBTreeIterator<T, T&, T*> iterator;iterator begin(){Node* left = _root;while (left && left->_left){left = left->_left;}return iterator(left);}iterator end(){return iterator(nullptr);}//插入pair<iterator,bool> insert(const T& date){KeyofT _com;if (_root == nullptr){_root = new Node(date);_root->_col = black;return make_pair(iterator(_root), true);}Node* parent = nullptr;Node* cur = _root;while (cur){if (_com(cur->_date)< _com(date)){parent = cur;cur = cur->_right;}else if (_com(cur->_date) > _com(date)){parent = cur;cur = cur->_left;}else{return make_pair(iterator(cur), false);}}cur = new Node(date);cur->_col = red;if (_com(parent->_date) < _com(date)){parent->_right = cur;}else {parent->_left = cur;}cur->_parent = parent;//Node* uncle=parent->_parent->while(parent && parent->_col == red){Node* grandfater = parent->_parent;assert(grandfater);assert(grandfater->_col==black);if (parent == grandfater->_left){Node* uncle = grandfater->_right;// 情况一 : uncle存在且为红,变色+继续往上处理if (uncle && uncle->_col == red){parent->_col = uncle->_col = black;grandfater->_col = red;// 继续往上处理cur = grandfater;parent = cur->_parent;}// 情况二+三:uncle不存在 + 存在且为黑else{// 情况二:右单旋+变色// g // p u// cif (cur == parent->_left){RotateR(grandfater);parent->_col = black;grandfater->_col = red;}else{// 情况三:左右单旋+变色// g // p u// cRotateL(parent);RotateR(grandfater);cur->_col = black;grandfater->_col = red;}break;}}else{Node* uncle = grandfater->_left;// 情况一if (uncle && uncle->_col == red){parent->_col = uncle->_col = black;grandfater->_col = red;// 继续往上处理cur = grandfater;parent = cur->_parent;}else{// 情况二:左单旋+变色// g // u p// cif (cur == parent->_right){RotateL(grandfater);parent->_col = black;grandfater->_col = red;}else{// 情况三:右左单旋+变色// g // u p// cRotateR(parent);RotateL(grandfater);cur->_col = black;grandfater->_col = red;}break;}}}_root->_col = black;return make_pair(iterator(cur), true);}void Inorder(){_Inorder(_root);}private://右旋void RotateR(Node* parent){Node* subl = parent->_left;Node* sublr = subl->_right;Node* prev = parent->_parent;parent->_left = sublr;if (sublr)sublr->_parent = parent;parent->_parent = subl;subl->_right = parent;if (_root == parent){_root = subl;subl->_parent = nullptr;}else{if (prev->_left == parent){subl->_parent = prev;prev->_left = subl;}else{subl->_parent = prev;prev->_right = subl;}}}//左旋void RotateL(Node* parent){Node* subr = parent->_right;Node* subrl = subr->_left;Node* prev = parent->_parent;parent->_right = subrl;if (subrl)subrl->_parent = parent;subr->_left = parent;parent->_parent = subr;if (_root == parent){_root = subr;subr->_parent = nullptr;}else{if (prev->_left == parent){subr->_parent = prev;prev->_left = subr;}else{subr->_parent = prev;prev->_right = subr;}}}//遍历void _Inorder(Node* _root){if (_root == nullptr)return;_Inorder(_root->_left);cout << _root->_date.first << " " << _root->_date.second << endl;_Inorder(_root->_right);}private:Node* _root = nullptr;};}
完整代码:
//在不同平台下需加不同头文件
#pragma once
using namespace std;
#include <iostream>
#include <assert.h>
#include "RedBlackTree.h"
#include <string>namespace sss
{template<class K>class Set{struct SetKeyofT{const K& operator()(const K& date){return date;}}; public:typedef typename RedBlackTree<K, K, SetKeyofT>::iterator iterator;iterator begin(){return _S.begin();}iterator end(){return _S.end();}pair<iterator, bool> Insert(const K& date){return _S.insert(date);}private:RedBlackTree<K, K, SetKeyofT> _S;};//测试用例/*void text_set(){string str[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };Set<string> hash;for (auto sh : str){hash.Insert(sh);}auto it = hash.begin();while (it != hash.end()){cout << *it << endl;++it;}}*/}namespace sss
{template<class K,class V> class Map{public:struct MapKeyofT{const K& operator()(const pair<K, V>& date){return date.first;}};typedef typename RedBlackTree<K, pair<K, V>, MapKeyofT>::iterator iterator;//t//ypedef RedBlackTree<K, pair<K, V>, MapKeyofT> RedBlackTree;iterator begin() {return _T.begin();}iterator end(){return _T.end();}pair<iterator, bool> Insert(const pair<K,V>& date){return _T.insert(date);}V& operator[](const K& key){pair<iterator, bool> ret = Insert(make_pair(key, V()));return ret.first->second;}private:RedBlackTree<K,pair<K,V>, MapKeyofT> _T;};//测试用例//void text_map()//{// Map<int, int> hash1;// hash1.Insert(make_pair(1,1));// cout<<hash1[1];// Map<string, int> hash2;// string str[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };// for (auto sh:str)// {// hash2[sh]++;// }// Map<string, int>::iterator it = hash2.begin();// while (it != hash2.end())// {// cout << it->first << ":" << it->second << endl;// ++it;// }// for (auto& kv : hash2)// {// cout << kv.first << ":" << kv.second << endl;// }// //hash1 = hash2;// //}
}namespace sss
{enum Color{red,black};template<class T>struct RedBlackTreeNode{RedBlackTreeNode<T>* _left;RedBlackTreeNode<T>* _right;RedBlackTreeNode<T>* _parent;//pair<K, V> _date;T _date;Color _col;RedBlackTreeNode(const T& date=T()):_left(nullptr),_right(nullptr),_parent(nullptr),_date(date)//, _col(black){}};template<class T, class Ref, class Ptr>struct __RBTreeIterator{typedef RedBlackTreeNode<T> Node;typedef __RBTreeIterator<T, Ref, Ptr> Self;Node* _node;__RBTreeIterator(Node* node):_node(node){}Ref operator*(){return _node->_date;}Ptr operator->(){return &_node->_date;}bool operator!=(const Self& _t){return _node != _t._node;}bool operator==(const Self& _t){return _node == _t._node;}Self* operator++(){if (_node->_right){Node* cur = _node;cur = cur->_right;while (cur->_left){cur = cur->_left;}_node=cur;}else{Node* parent = _node->_parent;Node* cur = _node;while (parent && cur == parent->_right){cur = cur->_parent;parent = parent->_parent;}_node=parent;}return this;}Self* operator--(){if (_node->_left){Node* cur = _node;cur = cur->_left;while (cur->_right){cur = cur->_right;}_node=cur;}else{Node* parent = _node->_parent;Node* cur = _node;while (parent && cur == parent->left){parent = parent->_parent;cur = parent;}_node= parent;}return this;}};template<class K, class T, class KeyofT>class RedBlackTree{typedef RedBlackTreeNode<T> Node;public: typedef __RBTreeIterator<T, T&, T*> iterator;iterator begin(){Node* left = _root;while (left && left->_left){left = left->_left;}return iterator(left);}iterator end(){return iterator(nullptr);}//插入pair<iterator,bool> insert(const T& date){KeyofT _com;if (_root == nullptr){_root = new Node(date);_root->_col = black;return make_pair(iterator(_root), true);}Node* parent = nullptr;Node* cur = _root;while (cur){if (_com(cur->_date)< _com(date)){parent = cur;cur = cur->_right;}else if (_com(cur->_date) > _com(date)){parent = cur;cur = cur->_left;}else{return make_pair(iterator(cur), false);}}cur = new Node(date);cur->_col = red;if (_com(parent->_date) < _com(date)){parent->_right = cur;}else {parent->_left = cur;}cur->_parent = parent;//Node* uncle=parent->_parent->while(parent && parent->_col == red){Node* grandfater = parent->_parent;assert(grandfater);assert(grandfater->_col==black);if (parent == grandfater->_left){Node* uncle = grandfater->_right;// 情况一 : uncle存在且为红,变色+继续往上处理if (uncle && uncle->_col == red){parent->_col = uncle->_col = black;grandfater->_col = red;// 继续往上处理cur = grandfater;parent = cur->_parent;}// 情况二+三:uncle不存在 + 存在且为黑else{// 情况二:右单旋+变色// g // p u// cif (cur == parent->_left){RotateR(grandfater);parent->_col = black;grandfater->_col = red;}else{// 情况三:左右单旋+变色// g // p u// cRotateL(parent);RotateR(grandfater);cur->_col = black;grandfater->_col = red;}break;}}else{Node* uncle = grandfater->_left;// 情况一if (uncle && uncle->_col == red){parent->_col = uncle->_col = black;grandfater->_col = red;// 继续往上处理cur = grandfater;parent = cur->_parent;}else{// 情况二:左单旋+变色// g // u p// cif (cur == parent->_right){RotateL(grandfater);parent->_col = black;grandfater->_col = red;}else{// 情况三:右左单旋+变色// g // u p// cRotateR(parent);RotateL(grandfater);cur->_col = black;grandfater->_col = red;}break;}}}_root->_col = black;return make_pair(iterator(cur), true);}void Inorder(){_Inorder(_root);}private://右旋void RotateR(Node* parent){Node* subl = parent->_left;Node* sublr = subl->_right;Node* prev = parent->_parent;parent->_left = sublr;if (sublr)sublr->_parent = parent;parent->_parent = subl;subl->_right = parent;if (_root == parent){_root = subl;subl->_parent = nullptr;}else{if (prev->_left == parent){subl->_parent = prev;prev->_left = subl;}else{subl->_parent = prev;prev->_right = subl;}}}//左旋void RotateL(Node* parent){Node* subr = parent->_right;Node* subrl = subr->_left;Node* prev = parent->_parent;parent->_right = subrl;if (subrl)subrl->_parent = parent;subr->_left = parent;parent->_parent = subr;if (_root == parent){_root = subr;subr->_parent = nullptr;}else{if (prev->_left == parent){subr->_parent = prev;prev->_left = subr;}else{subr->_parent = prev;prev->_right = subr;}}}//遍历void _Inorder(Node* _root){if (_root == nullptr)return;_Inorder(_root->_left);cout << _root->_date.first << " " << _root->_date.second << endl;_Inorder(_root->_right);}private:Node* _root = nullptr;};}