一、set
1.set简介和基本用法
set底层的实现就是红黑树
相较于算法中的 find O(N)
set用AVL树实现的find可以达到 O(logN)
用红黑树实现的find可以达到O(2logN)
将数据放入set中后会自动去重排序
2.multiset
相较于set少了去重的部分,可以让数据重复
find,erase等成员删除的都是中序遍历中第一个成员
二、map
1.pair(键值对)
template<class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair()
:first(T1()) //传入类型默认值构造
,second(T2())
{}
pair(const T1& a,const T2& b)
:first(a)
,second(b)
{}
};
2.插入
map<int, int> m;
m.insert(pair<int, int>(1, 1)); //相当于传入pair临时构造的匿名对象
//pair构造函数,构造一个匿名对象
m.insert(make_pair(2, 2)); //函数 模板 构造一个pair对象
//实际上更推荐用make_pair,不用声明模板参数,自动推断
map的插入返回值为
pair<iterator, bool> Insert(const T& data)
//当插入的数在map中没有时,则插入成功,返回插入val的迭代器(引用),和true
//当插入的数在map中已经有了,则插入失败,返回已经和val相同值的迭代器(引用),和false
作为其operator[]的底层
3.operator[]
map用来计数
map<string, int> countmap;
string strs[] = { "iphone","iphone","huawei","honor","huawei","summim" };
for (auto& e : strs)
{
map<string, int>::iterator ret = countmap.find(e);
if (ret != countmap.end())
//(*ret).second++;
ret->second++;
else
countmap.insert(make_pair(e, 1));
}
for (auto& e : countmap)
{
cout << e.first << ":" << e.second << endl;
}
也可以用operator[]更加便捷
map<string, int> countmap;
string strs[] = { "iphone","iphone","huawei","honor","huawei","summim" };
for (auto& e : strs)
{
//如果不在map中,则operator[]会插入pair<str,0> (0 == int() 即默认类型值) 返回映射对象(次数)的引用并且++
//如果在map中 ,则operator[]返回key对应的映射对象(次数)的应用,对其++
countmap[e]++;
}
operator的底层可以看作为
mapped_type& operator[](const key_type& k)
{
return (*((this->insert (make_pair(k, mapped_type()) )).first)).second;
//this->insert (make_pair(k, mapped_type()) 返回值为 pair<map<string,int>::iterator,bool>
//.first 取 map<string,int>::iterator
//* 取 pair<key_type,mapped_type>
//.second 取 mapped_type 并返回其引用
//返回引用的作用是,方便对其进行以后的操作
}
所以operator有三种用途
1.插入
2.查找k对应的映射对象
3.修改k对应的映射对象的值
map<string, int> countmap;
countmap["vivo"]; //插入
countmap["vivo"] = 1; //修改
cout << countmap["vivo"] << endl; //查找
countmap["oppo"] = 2; //插入+修改
map<string, string> dict;
dict.insert(make_pair("string", "字符串"));
dict["string"] = "字字符串";
dict["sort"] = "排序";
4.multimap
multimap也是去掉了查重的功能,但没有 operator[]
当有多个相同的键值时,不知道返回哪一个对应的val
三、模拟实现set,map
底层都是由红黑树实现的,为了方便了解逻辑,删除了红黑树部分接口
#pragma once
#include<iostream>
using namespace std;
template <class T, class Ref, class Ptr>
struct __BRTreeIterator
{
typedef BRTreeNode <T> Node;
Node* _node;
typedef __BRTreeIterator<T, Ref, Ptr> Self;
typedef __BRTreeIterator<T, T&, T*> iterator;
__BRTreeIterator(Node* node)
:_node(node)
{}
//普通迭代器时,是拷贝构造
//const迭代器,指出迭代器构造const迭代器
__BRTreeIterator(const iterator& s)
:_node(s._node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
Self operator++()
{
if (_node->_right)
{
Node* min = _node->_right;
while (min->_left)
{
min = min->_left;
}
_node = min;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
Self operator--()
{
if (_node->_left)
{
Node* max = _node->_left;
while (max->_right)
{
max = max->_right;
}
_node = max;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
bool operator==(const Self& s) const
{
return _node == s._node;
}
};
template<class K, class T, class KeyOfT>
class BRTree
{
public:
typedef BRTreeNode<T> Node;
typedef __BRTreeIterator<T, T&, T*> iterator;
typedef __BRTreeIterator<T, const T&, const T*> const_iterator;
iterator begin()
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return iterator(left);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator begin() const
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return const_iterator(left);
}
const_iterator end() const
{
return const_iterator(nullptr);
}
pair<iterator, bool> Insert(const T& data)
{
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = Black;
return make_pair(iterator(_root), true);
}
KeyOfT kot;
//父子节点确定插入的位置
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (kot(cur->_data) > kot(data))
{
parent = cur;
cur = cur->_left;
}
else if (kot(cur->_data) < kot(data))
{
parent = cur;
cur = cur->_right;
}
else
return make_pair(iterator(cur), false);
}
//走到这cur就是要插入的位置
//cur要连接parent,parent也要连接cur---判断靠kv的大小
cur = new Node(data);
Node* newnode = cur;
if (kot(parent->_data) > kot(cur->_data))
{
parent->_left = cur;
cur->_parent = parent;
}
else
{
parent->_right = cur;
cur->_parent = parent;
}
while (parent && parent->_col == Red)
{
Node* grandparent = parent->_parent;
//parent分在grandparent左右
if (grandparent->_left == parent)
{
//关键是看uncle节点不存在/红色/黑色的情况
Node* uncle = grandparent->_right;
if (uncle && uncle->_col == Red)
{
grandparent->_col = Red;
parent->_col = uncle->_col = Black;
.....
return make_pair(iterator(newnode), true);
}
private:
Node* _root = nullptr;
};
1.set
#include "RBTree.hpp"
namespace 9TSe
{
template<class K>
class Set
{
public:
struct SetKeyOfT
{
const K& operator()(const K& k)
{
return k;
}
};
typedef typename BRTree<K, K, SetKeyOfT>::const_iterator iterator;
typedef typename BRTree<K, K, SetKeyOfT>::const_iterator const_iterator;
pair<iterator, bool> Insert(const K& k)
{
return _t.Insert(k);
}
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
const_iterator begin() const
{
return _t.begin();
}
const_iterator end() const
{
return _t.end();
}
private:
BRTree<K, K, SetKeyOfT> _t;
};
set内数据本身是不能修改的
否则会破坏树的结构
所以迭代器都是由红黑树的const_iterator构成的
2.map
#include "RBTree.hpp"
namespace 9TSe
{
template<class K, class V>
class Map
{
public:
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
V& operator[](const K& k)
{
pair<iterator, bool> ret = Insert(make_pair(k, V()));
return ret.first->second;
}
typedef typename BRTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;
typedef typename BRTree<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;
pair<iterator, bool> Insert(const pair<K, V>& kv)
{
return _t.Insert(kv);
}
const_iterator begin() const
{
return _t.begin();
}
const_iterator end() const
{
return _t.end();
}
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
private:
BRTree<K, pair<const K, V>, MapKeyOfT> _t;
};