目录
1. 关联式容器
STL将自己的数据结构分为六大组件,
容器分为:
序列式容器:vector list …
类似于数据结构中的线性表,数据和数据之间没有关联,为了单纯的存储数据,
关联式容器:map和set…
底层是:平衡搜索树,数据和数据之间具有强烈的关系
2. 键值对
3. 树形结构的关联式容器
4. set 和 map简单使用:
set简单使用
insert
#include<set>
#include<iostream>
using namespace std;
void test_set1()
{
set<int> s;
s.insert(1);
s.insert(5);
s.insert(3);
s.insert(4);
s.insert(2);
s.insert(2);
set<int>::iterator it = s.begin();
while (it != s.end()) {
cout << *it << " ";
++it;
}
cout << endl;
auto it1 = s.begin();
for (auto it1 : s)
{
cout << it1 << " ";
}
cout << endl;
}
int main()
{
test_set1();
return 0;
}
1 2 3 4 5
1 2 3 4 5
所以走的是中序
因为没有重复,所以排序+去重
erase
#include<set>
#include<iostream>
using namespace std;
void test_set1()
{
set<int> s;
s.insert(1);
s.insert(5);
s.insert(3);
s.insert(4);
s.insert(2);
s.insert(2);
set<int>::iterator it = s.begin();
while (it != s.end()) {
cout << *it << " ";
++it;
}
cout << endl;
set<int>::iterator pos = s.find(2);
//当没有找到这个值的时候,还要删除,就会报错
if (pos != s.end()) {
//pos必须是一个有效位置的迭代器
s.erase(pos);
}
//直接使用值也是可以的
//找到就删除,没有找到就直接返回
s.erase(3);
s.erase(30);
auto it1 = s.begin();
for (auto it1 : s){
cout << it1 << " ";
}
cout << endl;
}
int main()
{
test_set1();
return 0;
}
vs multiset
set是排序+去重
multiset是排序
multi:多种
find
void test(){
multiset<int> s;
s.insert(2);
s.insert(1);
s.insert(5);
s.insert(2);
s.insert(3);
s.insert(4);
s.insert(2);
s.insert(2);
//找到的是那个2?
//multiset<int>::iterator pos = s.find(2);
auto pos = s.find(2);
while (pos != s.end())
{
cout << *pos << " ";
++pos;
}
cout << endl;
}
//2 2 2 2 3 4 5
//中序的第一个一,不一定是叶子
int main()
{
test();
return 0;
}
erase
void test() {
multiset<int> s;
s.insert(2);
s.insert(1);
s.insert(5);
s.insert(2);
s.insert(3);
s.insert(4);
s.insert(2);
s.insert(2);
auto pos = s.find(2);
//方式一:
//while (pos != s.end() && *pos==2)
//{
// auto newpos = pos;
// newpos++;
// s.erase(pos);
// pos = newpos;
//}
//方式二:
cout << s.erase(2) << endl;
//4
//1 3 4 5
multiset<int>::iterator it1 = s.begin();
for (auto it1 : s) {
cout << it1 << " ";
}
cout << endl;
}
int main()
{
test();
return 0;
}
map的简单使用
insert
void test1()
{
map<string, string> dict;
pair<string, string> kv1("红色", "red");
dict.insert(kv1);
dict.insert(pair<string, string>("蓝色","blue"));
//自动推导类型
dict.insert(make_pair("黄色", "yellow"));//推荐
dict.insert({"苹果","apple"});//C++11语法
map<string, string>::iterator it = dict.begin();
while (it != dict.end())
{
cout << (*it).first << " " << (*it).second << endl;
cout << it->first << " " << it->second << endl;
++it;
}
cout << endl;
for (auto& kv : dict)
{
cout << kv.first << " " << kv.second << endl;
}
}
int main()
{
test1();
return 0;
}
operator[]
void test()
{
string arr[] = { "苹果","香蕉", "苹果", "梨", "苹果", "苹果" };
map<string, int> countMap;
//first
//for (auto& str : arr)
//{
// auto ret = countMap.find(str);
// if (ret == countMap.end())//没有找到
// {
// countMap.insert(make_pair(str, 1));
// }
// else {
// ret->second++;
// }
//}
//second
//for (auto& str : arr)
//{
// auto kv = countMap.insert(make_pair(str, 1));
// if (kv.second==false) {
// kv.first->second++;
// }
//}
//third
for (auto& str : arr){
countMap[str]++;
}
for (auto& kv : countMap){
cout << kv.first << " " << kv.second << endl;
}
}
operator[]功能:
1.插入
2.查找(key 对应的 value)
3.修改(key 对应的 value)
void test()
{
map<string, string> dict;
dict.insert(make_pair("right", "右边"));
dict.insert(make_pair("left", "左边"));
dict.insert(make_pair("left", "中间"));//插入,但是不成功
dict["left"] = "做边";//修改,成功
dict["test"];//插入,test对应的value=""
dict["right"];
cout << dict["mid"] << endl;//先插入,然后在输出""
}
int main()
{
test();
return 0;
}
multimap
void test()
{
multimap<string, string> dict;
dict.insert(make_pair("left", "左边"));
dict.insert(make_pair("left", "左边"));
dict.insert(make_pair("left", "中间"));
dict.insert(make_pair("right", "右边"));
for (auto& kv : dict) {
cout << kv.first << " " << kv.second << endl;
}
}
//left 左边
//left 左边
//left 中间
//right 右边
int main()
{
test();
return 0;
}
延伸:
multimap没有[]
查找也是第一个
5. set和map相关题
1.map关于second的排序
一vector
struct CountVal
{
bool operator()(const pair<string, int>& left,const pair<string,int>& right)
{
return left.second > right.second;
}
};
void GetFavoriteFruit(const vector<string>& fruits, size_t k)
{
map<string, int> countMap;
for (auto& str : fruits)
{
countMap[str]++;
}
//1.数据量不大,排序
vector<pair<string, int>> sortV;
for (auto& kv : countMap)
{
sortV.push_back(kv);
}
sort(sortV.begin(), sortV.end(), CountVal());
for (int i = 0; i < k; i++)
{
cout << sortV[i].first << ":" << sortV[i].second << endl;
}
}
int main()
{
vector<string> arr = { "苹果","香蕉", "苹果", "梨", "杏", "苹果",
"苹果","香蕉", "桃", "梨", "苹果", "苹果" };
GetFavoriteFruit(arr, 3);
return 0;
}
二vector+迭代器
struct CountInterVal
{
bool operator()(const map<string, int>::iterator& left, const map<string, int>::iterator& right) {
return left->second > right->second;
}
};
void GetFavoriteFruit(const vector<string>& fruits, size_t k)
{
map<string, int> countMap;
for (auto& str : fruits)
countMap[str]++;
vector<map<string, int>::iterator> sortV;
auto it = countMap.begin();
while (it != countMap.end()){
sortV.push_back(it);
++it;
}
sort(sortV.begin(), sortV.end(), CountInterVal());
for (int i = 0; i < k; i++)
cout << sortV[i]->first << ":" << sortV[i]->second << endl;
}
int main()
{
vector<string> arr = { "苹果","香蕉", "苹果", "梨", "杏", "苹果",
"苹果","香蕉", "桃", "梨", "苹果", "苹果" };
GetFavoriteFruit(arr, 3);
return 0;
}
三multimap+迭代器
struct CountInterVal
{
bool operator()(const map<string, int>::iterator& left, const map<string, int>::iterator& right) {
return left->second > right->second;
}
};
void GetFavoriteFruit(const vector<string>& fruits, size_t k)
{
map<string, int> countMap;
for (auto& str : fruits)
countMap[str]++;
multimap<int,string,greater<int>> sortMap;
for (auto& kv : countMap) {
sortMap.insert(make_pair(kv.second,kv.first));
}
}
int main()
{
vector<string> arr = { "苹果","香蕉", "苹果", "梨", "杏", "苹果",
"苹果","香蕉", "桃", "梨", "苹果", "苹果" };
GetFavoriteFruit(arr, 3);
return 0;
}
四优先级队列
struct CountVal
{
bool operator()(const pair<string, int>& left, const pair<string, int>& right)
{
return left.second < right.second;
}
};
void GetFavoriteFruit(const vector<string>& fruits, size_t k)
{
map<string, int> countMap;
for (auto& str : fruits)
countMap[str]++;
priority_queue<pair<string, int>, vector<pair<string, int>>, CountVal> pq;
for (auto& kv : countMap) {
pq.push(kv);
}
while (k--) {
cout << pq.top().first << pq.top().second << endl;
pq.pop();
}
}
int main()
{
vector<string> arr = { "苹果","香蕉", "苹果", "梨", "杏", "苹果",
"苹果","香蕉", "桃", "梨", "苹果", "苹果" };
GetFavoriteFruit(arr, 3);
return 0;
}
五优先级队列+迭代器
struct CountIterVal
{
bool operator()(const map<string, int>::iterator& left, const map<string, int>::iterator& right) {
return left->second < right->second;
}
};
void GetFavoriteFruit(const vector<string>& fruits, size_t k)
{
map<string, int> countMap;
for (auto& str : fruits)
countMap[str]++;
priority_queue<map<string, int>::iterator, vector<map<string, int>::iterator>, CountIterVal> pq;
auto it = countMap.begin();
while (it != countMap.end()){
pq.push(it);
++it;
}
while (k--){
cout << pq.top()->first << ":" << pq.top()->second << endl;
pq.pop();
}
cout << endl;
}
int main()
{
vector<string> arr = { "苹果","香蕉", "苹果", "梨", "杏", "苹果",
"苹果","香蕉", "桃", "梨", "苹果", "苹果" };
GetFavoriteFruit(arr, 3);
return 0;
}
2.前K个高频单词
链接: 前K个高频单词
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));
vector<string> v;
auto it = sortMap.begin();
while(k--){
v.push_back(it->second);
++it;
}
return v;
}
};
4. 底层结构
4.1AVL树/高度平衡二叉搜索树
概念:
二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下
当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
它的左右子树都是AVL树
左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)
如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在O( log2n) ,搜索时间复杂度O( log2n)。
4.2简单模拟实现链接:
4.3红黑树
概念:
红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的
性质:
- 每个结点不是红色就是黑色
- 根节点是黑色的
- 如果一个节点是红色的,则它的两个孩子结点是黑色的(说明:树中没有连续的红色节点)
- 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点(说明:每条路径黑色节点的数量相等)
- 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
思考:为什么满足上面的性质,红黑树就能保证:其最长路径中节点个数不会超过最短路径节点个数的两倍?
最短路径:全黑
最长路径:一黑一红
假设每条路径黑节点的数量是:N
N <= 任意路径长度 <= 2N
底层简单模拟实现,以及实现中遇见的问题
https://blog.csdn.net/sakeww/article/details/125036961