目录
8. std::multiset 跟set接口一样,只是允许冗余,不去重
①map是C++98中已存在的,unordered_map是C++11中才有的
②map中都重载了[]运算符,multimap中没有重载[]运算符,set也没有重载[]。
③map中key不能修改,因为如果修改了就不能保证红黑树的有序特性了
①set中也可以存储键值对,实例化set时,将set中元素类型设置为pair即可
②set默认是升序,但是其内部默认不是按照大于比较,而是按照 less小于比较
3.insert写法提高 记录水果次数 的效率(不这么写,只是为[]做铺垫)
(3)做法三:sort 非稳定排序,可以控制比较方法使其稳定
一.set介绍
1.set介绍
set 是一个K模型的搜索二叉树 #include<set>
2.insert 使用
(1)和(2)相当于一样,在pos位置插入也会自动排序
insert :排序 + 去重
void test_set1()
{
set<int> s;
s.insert(4);
s.insert(5);
s.insert(2);
s.insert(1);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(1);
// 排序 + 去重
set<int>::iterator it = s.begin();
while (it != s.end())
{
//*it = 10; 迭代器不支持修改
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
}
set中的普通迭代器就是用的const迭代器!!
3.find
能找到就返回元素的迭代器,找不到就返回end
set::find和std::find对比
set::find 搜索二叉树特性查找,时间复杂度是O(logN)
全局的find 是暴力查找,时间复杂度是O(N)
所以set::find效率更高
void test_set2()
{
set<int> s;
s.insert(4);
s.insert(5);
s.insert(2);
s.insert(1);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(1);
set<int>::iterator pos = s.find(20); // O(logN)
if (pos != s.end())
{
cout << "set.find找到了" << endl;
}
pos = find(s.begin(), s.end(), 2); // O(N)
if (pos != s.end())
{
cout << "find找到了" << endl;
}
}
4.erase
size_type就是size_t,也就是unsigned int
(1) void erase (iterator position); 必须加检查if (pos != s.end()) s.erase(pos); 因为有pos时,正常运行,如果没有pos,就会报错。例如:s.erase(pos);
(2)size_ type erase (const value_ type& val) ; 则可以随便删,无论有没有都不报错 例如:s.erase(3)
(3)void erase (iterator first,iterator last) 删的是[ first, last),即不包含 last
void test_set3()
{
set<int> s;
s.insert(4);
s.insert(5);
s.insert(2);
s.insert(1);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(1);
cout << s.erase(3) << endl; //有就返回1
cout << s.erase(30) << endl; //没有就返回0
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
set<int>::iterator pos = s.find(3);
if (pos != s.end())
s.erase(pos);
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
5.swap 根节点交换
6.count 比find方便
if (s.count(5))
{
cout << "5在" << endl;
}
if (s.find(5) != s.end())
{
cout << "5在" << endl;
}
打印:
5在
5在
7.lower_bound:返回>= val得位置迭代器
(1)lower_bound
返回>= val得位置迭代器 3返回3位置 6 返回7位置
返回>= val的位置迭代器 3返回3位置 6 返回7位置
set<int> s;
s.insert(4);
s.insert(5);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(7);
s.insert(9);
set<int>::iterator lowIt = s.lower_bound(3); 存在
lowIt = s.lower_bound(6); 不存在
用途:举例:要求删除>=x的所有值:
void test_set4()
{
set<int> s;
s.insert(4);
s.insert(5);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(7);
s.insert(9);
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
// 要求删除>=x的所有值
int x;
cin >> x;
set<int>::iterator lowIt = s.lower_bound(x);
s.erase(lowIt, s.end());
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
}
(2)upper_bound 返回>x位置的迭代器
返回>x位置的迭代器,s.upper_bound(5) 存在5,不存在6,则返回7;s.upper_bound(6) 不存在6,返回7;
set<int> s;
s.insert(4);
s.insert(5);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(7);
s.insert(9);
返回>x位置的迭代器 -》 都是返回 7位置的迭代器
set<int>::iterator upIt = s.upper_bound(5); // 存在
upIt = s.upper_bound(6); // 不存在
用途:例如 删除x <= <= y的区间 删除 [x,y]
void test_set4()
{
set<int> s;
s.insert(4);
s.insert(5);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(7);
s.insert(8);
// 返回>= val得位置迭代器 3返回3位置 6 返回7位置
/*set<int>::iterator lowIt = s.lower_bound(3); 存在
lowIt = s.lower_bound(6); 不存在*/
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
// 删除x <= <= y的区间 删除 [x,y]
int x, y;
cin >> x >> y;
auto leftIt = s.lower_bound(x); // [
auto rightIt = s.upper_bound(y); // )
s.erase(leftIt, rightIt);
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
}
8. std::multiset 跟set接口一样,只是允许冗余,不去重
插入重复的数时set会去重,multiset不去重,允许冗余
不同:
multiset 的count和erase 返回查找或删除个数
find(x) 多个x的话,find返回中序第一个x
void test_set6()
{
multiset<int> s;
s.insert(4);
s.insert(5);
s.insert(2);
s.insert(1);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(1);
s.insert(3);
s.insert(3);
s.insert(3);
s.insert(3);
// 排序
set<int>::iterator it = s.begin(); //迭代器打印
while (it != s.end())
{
//*it = 10;
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : s) //范围for打印
{
cout << e << " ";
}
cout << endl;
cout << s.count(1) << endl; //测试count,打印3,因为1有3个
cout << s.erase(1) << endl; //测试erase,打印3,因为1有3个
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
auto pos = s.find(3); // 多个x的话,find返回中序第一个x
while (pos != s.end()) //从中序第一个3开始打印完整个
{
cout << *pos << " ";
++pos;
}
cout << endl;
}
9.set相关题目
方法一:把nums1和nums2分别放进s1和s2中进行去重,再利用范围for把s2中的每个元素在s1中进行查找,如果找到就放进v中。时间复杂度是:O(n*logn) n个节点,每个节点找logn高度次
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
//去重
set<int> s1;
for(auto e:nums1)
{
s1.insert(e);
}
//去重
set<int> s2;
for(auto e:nums2)
{
s2.insert(e);
}
vector<int> v;
for(auto e:s2)
{
if(s1.count(e))
{
v.push_back(e);
}
}
return v;
}
};
方法二:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
set<int> s1;
for(auto e:nums1)
{
s1.insert(e);
}
set<int> s2;
for(auto e:nums2)
{
s2.insert(e);
}
vector<int> v;
set<int>::iterator it1=s1.begin();
set<int>::iterator it2=s2.begin();
while(it1!=s1.end() && it2!=s2.end())
{
if(*it1>*it2) //相比较,值小的++
{
++it2;
}
else if(*it1<*it2) //相比较,值小的++
{
++it1;
}
else //相比较,值相等就放进v中,同时++
{
v.push_back(*it1);
++it1;
++it2;
}
}
return v;
}
};
二.map用法介绍
map是KV模型的搜索二叉树,insert和[]用法是重点,其他用法参考set #include<map>
几个map和set的冷知识:
map:
①map是C++98中已存在的,unordered_map是C++11中才有的
②map中都重载了[]运算符,multimap中没有重载[]运算符,set也没有重载[]。
原因:map中key是唯一的,每个key都有与之对应的value,经常需要通过key获取value,因此 map为了形象简单 就重载了[]运算符, multimap中key是可以重复的,如果重载了[]运算符,给定 一个key时,就没有办法返回 value了,因此,multimap中没有重载[]运算符
③map中key不能修改,因为如果修改了就不能保证红黑树的有序特性了
set:
①set中也可以存储键值对,实例化set时,将set中元素类型设置为pair即可
②set默认是升序,但是其内部默认不是按照大于比较,而是按照 less小于比较
less是把小的放左边,所以是升序;greater是把大的放左边,所以是降序
③map和set查询的时间复杂度都是O(log_2N)
解释:map和set的底层结构都是红黑树,而红黑树是近似的平衡二叉搜索树,故查询时间 复杂度为O(log_2N)
④map和set底层都是使用红黑树实现的
1.pair和make_pair
(1)pair键值对 的介绍
pair 打包了KV模型的key和val两个类型的值,c++不支持返回两个值,也就不知道返回key和val哪一个了,所以干脆打包key和val,返回一个pair结构
(value_type 是 pair<const key_type,mapped_type>)
pair中的first就相当于KV模型中的key,second相当于KV模型中的val
(2)make_pair 介绍
make_pair 相当于返回了一个pair的匿名对象
2.map的遍历
(1)英汉字典的遍历
几种插入英汉字典的方式:匿名对象插入,普通对象插入,make_pair插入
void test_map1()
{
map<string, string> dict;
// pair构造函数
dict.insert(pair<string, string>("sort", "排序")); //匿名对象插入更便捷
pair<string, string> kv("insert", "插入"); //普通对象插入
dict.insert(kv);
// make_pair
auto ret1 = dict.insert(make_pair("left", "左边")); //make_pair插入
auto ret2 = dict.insert(make_pair("left", "剩余"));
// 遍历
//map<string, string>::iterator it = dict.begin();
auto it = dict.begin();
while (it != dict.end())
{
//cout << *it << " "; // it->operator*()
//cout << (*it).first << ":" << (*it).second << endl;
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
for (const auto& kv : dict)
{
cout << kv.first << ":" << kv.second << endl;
}
}
int main()
{
test_map1();
return 0;
}
(2)记录水果次数
void test_map2()
{
string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
map<string, int> countMap;
for (auto& str : arr)
{
map<string, int>::iterator it = countMap.find(str);
if (it != countMap.end()) //如果countMap中有,就计数加1
{
it->second++;
}
else
{
countMap.insert(make_pair(str, 1)); //没有就插入水果
}
}
for (auto& str : arr)
{
countMap[str]++;
}
for (const auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
}
3.insert写法提高 记录水果次数 的效率(不这么写,只是为[]做铺垫)
map的insert默认是按照pair中的first进行排序的
string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
map<string, int> countMap;
for (auto& str : arr)
{
pair<map<string, int>::iterator, bool> ret = countMap.insert(make_pair(str, 1));
//或者 auto ret = countMap.insert(make_pair(str, 1));
if (ret.second == false)
{
ret.first->second++;
}
}
for (const auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
解释:
pair<map<string, int>::iterator, bool> ret = countMap.insert(make_pair(str, 1)) 插入节点,若插入成功,ret.first这个iterator 存的是新插入节点的迭代器,ret.second 存的是true;若插入失败,ret.first这个iterator 存的是已有的相同节点的迭代器,ret.second 存的是false;插入失败就再记录个数++就行,ret.first->second++; 用于访问记录水果个数,ret.first 是节点迭代器,ret.first->second++; 节点中的second用于记录对应水果的个数
4.operator[] 运算符重载
(1) 提高 记录水果次数 的效率的真正写法:
void test_map2()
{
string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
map<string, int> countMap;
for (auto& str : arr)
{
countMap[str]++;
}
for (const auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
}
解释:
countMap[str]++; 中 countMap[str] 返回的是新插入节点中的 次数second 。
如果插入的str不在 对象countMap中,countMap[str]++; 就是插入这个节点,迭代器就是新节点的迭代器,看原码可知 int类型的次数second用的是缺省值(对应原码中的mapped_typed(),是缺省值 ),所以开始second就是0,++后就是1。作用就是插入并修改val (val意思就是second)。
如果插入的str在 对象countMap中,countMap[str]++; 就是查找到这个节点,迭代器就是已有节点的迭代器,int类型的次数second在第一次已经是1了,++后就是2。作用就是插入并修改val (val意思就是second,用于计水果次数)。
(2) 字典中利用[]插入或修改 示例
void test_map1()
{
map<string, string> dict;
// pair构造函数
dict.insert(pair<string, string>("sort", "排序"));
pair<string, string> kv("insert", "插入");
dict.insert(kv);
// make_pair
auto ret1 = dict.insert(make_pair("left", "左边"));
auto ret2 = dict.insert(make_pair("left", "剩余"));
dict["operator"] = "重载"; // 插入+修改
dict["left"] = "左边、剩余"; // 修改
dict["erase"]; // 插入
cout << dict["left"] << endl; // 查找
}
5.multimap 允许键值冗余
相比map,multimap使用函数接口最大的区别是什么?
答:不支持operator[] 。
三.相关题目
1.692. 前K个高频单词
(1)做法一:stable_sort稳定排序
把map中的pair放到v中再用stable_sort稳定排序,再把各个pair对应的first放到vv中,再输出vv
class Solution {
public:
typedef map<string,int>::iterator CountIter;
struct less
{
bool operator()(const pair<string,int>& x,const pair<string,int>& y)
{
return x.second>y.second;
}
};
vector<string> topKFrequent(vector<string>& words, int k) {
map<string,int> countMap;
for(auto& str:words)
{
countMap[str]++;
}
vector<pair<string,int>> v;
CountIter it=countMap.begin();
while(it!=countMap.end())
{
//cout<<it->first<<" "<<it->second<<endl;
v.push_back(*it);
++it;
}
stable_sort(v.begin(),v.end(),less()); //stable_sort稳定排序
vector<string> vv;
for(int i=0;i<k;i++)
{
vv.push_back(v[i].first);
}
for(auto e:v)
{
cout<<e.first<<" "<<e.second<<endl;
}
return vv;
}
};
(2)做法二:stable_sort稳定排序 2
与做法一不同的是:pair很大,为了减少拷贝,我们可以选择不拷贝pair而是拷贝迭代器,把map中的迭代器放到v中,比较方法中通过迭代器找到second,再用stable_sort稳定排序这些迭代器,再把各个迭代器对应的first放到vv中,再输出vv
自己敲的:
class Solution {
public:
typedef map<string,int>::iterator CountIter;
struct less //降序
{
bool operator()(const CountIter& x,const CountIter& y)
{
return x->second > y->second;
}
};
vector<string> topKFrequent(vector<string>& words, int k) {
map<string,int> countMap;
for(auto& str:words)
{
countMap[str]++;
}
vector<CountIter> v;
CountIter it=countMap.begin();
while(it!=countMap.end())
{
//cout<<it->first<<" "<<it->second<<endl;
v.push_back(it);
++it;
}
stable_sort(v.begin(),v.end(),less()); //stable_sort稳定排序
for(auto e:v)
{
cout<<e->first<<" "<<e->second<<endl;
}
vector<string> vv;
for(int i=0;i<k;i++)
{
vv.push_back(v[i]->first);
}
return vv;
}
};
(3)做法三:sort 非稳定排序,可以控制比较方法使其稳定
相比较上面的方法,把stable_sort换成sort后,只需要控制比较方法即可使其稳定:因为map中默认是按照分first小的在前排序的,sort 时我们设计的比较方法是按second排序的,但是当second相等时,sort有可能打乱之前map中按 first 排的先后顺序,这样就是不稳定。我们只需要比较方法中让second相等时的情况再按first小的在前排好就可以达到稳定的目的。(相等时会多比一下first,会影响一点效率)
自己敲的:
(4)做法四:利用map自身按照first排序
map的insert默认是按照pair中的first进行排序的,因此我们可以创建一个sortMap,int对应first,string对应second,然后一个一个从kv中插入进sortMap(kv中的first和second颠倒一下插入进去),因为map默认去掉重复的first,这样会导致把次数重复的元素去掉(因为次数放在了first位置),因此要用允许重复的multimap,插入顺序map默认是less降序,因为是top-k问题,我们要把map中插入顺序改成升序插入greater<int>。
class Solution {
public:
vector<string> topKFrequent(vector<string>& words, int k) {
map<string,int> countMap;
for(auto& str:words)
{
countMap[str]++;
}
//排序
multimap<int,string,greater<int>> sortMap;
for(auto& kv:countMap)
{
sortMap.insert(make_pair(kv.second,kv.first));
}
// auto it=sortMap.begin();
// while(it!=sortMap.end())
// {
// cout<<it->first<<" "<<it->second<<endl;
// ++it;
// }
vector<string> vv;
auto it=sortMap.begin();
for(int i=0;i<k;i++)
{
vv.push_back(it->second);
++it;
}
return vv;
}
};
官方写法:
四.用红黑树模拟实现map,set
重点:
struct SetKeyOfT 仿函数,用于在RBTree.h找到map/set中所要比较的值,用于控制RBTree.h中pair类型的比较方法,因为库中的pair类型 先比first再比second 的比较方法不是我们想要的
Map.h
#pragma once
#include "RBTree.h"
namespace bit
{
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;
typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::const_iterator const_iterator;
iterator begin()
{
return _t.Begin();
}
iterator end()
{
return _t.End();
}
pair<iterator, bool> insert(const pair<K, V>& kv)
{
return _t.Insert(kv);
}
iterator find(const K& key)
{
return _t.Find(key);
}
V& operator[](const K& key)
{
pair<iterator, bool> ret = insert(make_pair(key, V()));
return ret.first->second;
}
private:
RBTree<K, pair<K, V>, MapKeyOfT> _t;
};
void test_map1()
{
map<string, int> m;
m.insert(make_pair("111", 1));
m.insert(make_pair("555", 5));
m.insert(make_pair("333", 3));
m.insert(make_pair("222", 2));
map<string, int>::iterator it = m.begin();
while (it != m.end())
{
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
for (auto& kv : m)
{
cout << kv.first << ":" << kv.second << endl;
}
cout << endl;
}
void test_map2()
{
string arr[] = { "ƻ", "", "ƻ", "", "ƻ", "ƻ", "", "ƻ", "㽶", "ƻ", "㽶" };
map<string, int> countMap;
for (auto& str : arr)
{
countMap[str]++;
}
for (const auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
}
void test_map3()
{
map<string, string> dict;
dict["insert"];
dict["insert"] = "";
dict["left"] = "";
}
}
Set.h
#pragma once
#include "RBTree.h"
namespace bit
{
template<class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
iterator begin() const //set内容不想被修改(key值不修改),则给this设置const,
{ //调用时会调用带const的Begin()
return _t.Begin();
}
iterator end() const
{
return _t.End();
}
pair<iterator, bool> insert(const K& key)
{
//pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(key);
auto ret = _t.Insert(key);
return pair<iterator, bool>(iterator(ret.first._node), ret.second);
}
iterator find(const K& key)
{
return _t.Find(key);
}
private:
RBTree<K, K, SetKeyOfT> _t;
};
void test_set1()
{
set<int> s;
s.insert(8);
s.insert(6);
s.insert(11);
s.insert(5);
s.insert(6);
s.insert(7);
s.insert(10);
s.insert(13);
s.insert(12);
s.insert(15);
set<int>::iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
}
}
RBTree.h
pragma once
enum Colour
{
RED,
BLACK,
};
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data; // 数据
Colour _col;
RBTreeNode(const T& data)
:_data(data)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
{}
};
template<class T, class Ref, class Ptr>
struct __RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef __RBTreeIterator<T, Ref, Ptr> Self;
Node* _node;
__RBTreeIterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
// 休息17:00
Self& operator++() //中序遍历
{
if (_node->_right == nullptr) //当前节点的右节点为空
{
// 就找祖先里面,孩子是父亲左的那个父亲
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && parent->_right == cur)
{ //只要这个父亲的孩子不是父亲的左,就继续往上找
cur = cur->_parent;
parent = parent->_parent;
}
//直到这个父亲的孩子是父亲的左,这个父亲就是该++走到的节点
_node = parent;
}
else //当前节点的右节点不为空
{
// 就走完右子树的最左节点
Node* subLeft = _node->_right;
while (subLeft->_left)
{
subLeft = subLeft->_left;
}
_node = subLeft;
}
return *this;
}
Self operator++(int)
{
Self tmp(*this);
++(*this);
return tmp;
}
Self& operator--()
{
if (_node->_left == nullptr)
{
// 找祖先里面,孩子是父亲
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
else
{
// 左子树的最右节点
Node* subRight = _node->_left;
while (subRight->_right)
{
subRight = subRight->_right;
}
_node = subRight;
}
return *this;
}
Self operator--(int)
{
Self tmp(*this);
--(*this);
return tmp;
}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
bool operator==(const Self& s) const
{
return _node == s->_node;
}
};
// T决定红黑树存什么数据
// set RBTree<K, K>
// map RBTree<K, pair<K, V>>
// KeyOfT -> 支持取出T对象中key的仿函数
template<class K, class T, class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef __RBTreeIterator<T, T&, T*> iterator;
typedef __RBTreeIterator<T, const T&, const T*> const_iterator;
// 构造 拷贝构造 赋值 和析构 跟搜索树实现方式是一样的
iterator Begin()
{
Node* subLeft = _root;
while (subLeft && subLeft->_left)
{
subLeft = subLeft->_left;
}
return iterator(subLeft);
}
iterator End()
{
return iterator(nullptr);
}
const_iterator Begin() const
{
Node* subLeft = _root;
while (subLeft && subLeft->_left)
{
subLeft = subLeft->_left;
}
return const_iterator(subLeft);
}
const_iterator End() const
{
return const_iterator(nullptr);
}
pair<iterator, bool> Insert(const T& data)
{
// 1、搜索树的规则插入
// 2、看是否违反平衡规则,如果违反就需要处理:旋转
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->_right;
}
else if (kot(cur->_data) > kot(data))
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(iterator(cur), true);
}
}
cur = new Node(data);
Node* newnode = cur;
cur->_col = RED;
if (kot(parent->_data) < kot(data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
// 存在连续红色节点
while (parent && parent->_col == RED)
{
Node* grandfater = parent->_parent;
assert(grandfater);
if (grandfater->_left == parent)
{
Node* uncle = grandfater->_right;
// 情况一:
if (uncle && uncle->_col == RED) // 叔叔存在且为红
{
// 变色
parent->_col = uncle->_col = BLACK;
grandfater->_col = RED;
// 继续往上处理
cur = grandfater;
parent = cur->_parent;
}
else // 叔叔不存在 或者 叔叔存在且为黑
{
if (cur == parent->_left) // 单旋
{
// g
// p
// c
RotateR(grandfater);
parent->_col = BLACK;
grandfater->_col = RED;
}
else // 双旋
{
// g
// p
// c
RotateL(parent);
RotateR(grandfater);
cur->_col = BLACK;
grandfater->_col = RED;
}
break;
}
}
else //(grandfater->_right == parent)
{
Node* uncle = grandfater->_left;
// 情况一:
if (uncle && uncle->_col == RED)
{
// 变色
parent->_col = uncle->_col = BLACK;
grandfater->_col = RED;
// 继续往上处理
cur = grandfater;
parent = cur->_parent;
}
else
{
if (cur == parent->_right)
{
// g
// p
// c
RotateL(grandfater);
parent->_col = BLACK;
grandfater->_col = RED;
}
else // 双旋
{
// g
// p
// c
RotateR(parent);
RotateL(grandfater);
cur->_col = BLACK;
grandfater->_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;
if (subRL)
subRL->_parent = parent;
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (parent == _root)
{
_root = subR;
_root->_parent = nullptr;
}
else
{
if (parent == ppNode->_left)
{
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;
Node* ppNode = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (parent == _root)
{
_root = subL;
_root->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
}
iterator Find(const K& key)
{
Node* cur = _root;
KeyOfT kot;
while (cur)
{
if (kot(cur->_data) < key)
{
cur = cur->_right;
}
else if (kot(cur->_data) > key)
{
cur = cur->_left;
}
else
{
return iterator(cur);
}
}
return End();
}
private:
Node* _root = nullptr;
};