map和set都是关联式容器,它们有一些共同的特性:
1. 存储方式:map和set都是基于红黑树(Red-Black Tree)实现的,这使得它们内部的元素是有序的,根据特定的排序准则进行排列。
2. 唯一性:set中的元素是唯一的,任何两个元素之间都不相等。而在map中,每个键都是唯一的。
3. 查找效率:由于内部使用了红黑树实现,map和set都具有较高的查找效率,时间复杂度为O(log n)。
4. 插入和删除操作:对于插入和删除操作,同样由于红黑树的特性,map和set的操作效率也较高,时间复杂度也为O(log n)。
5. 没有随机访问:与vector和deque不同的是,map和set不支持通过下标随机访问元素,因为元素是按照排序规则存储的。
总的来说,map和set是高效的关联式容器,适合在需要进行快速查找、插入和删除操作,并且要求元素按照一定规则有序存储的情况下使用。
// set 底层是 key 模型搜索树 , 不允许重复 数值 , 不允许 修改
// 底层是 红黑树 实现 , 时间复杂度为O(log n)
// 1.存储无序且不重复的元素
// 2.快速查找、删除和插入元素
// 3.去除重复元素
// 4.进行集合间的交集、并集、差集等操作
/*
#include<iostream>
#include<set>
#include<vector>
using namespace std;
void test1()// 作用
{
set<int> s1;
s1.insert(10);
s1.insert(40);
s1.insert(60);
s1.insert(30);
s1.insert(40);
s1.insert(20);
// 排序 + 去重
set<int>::iterator it = s1.begin();
while (it != s1.end())
{
cout << *it << " ";//10 30 40 60
it++;
}
cout << endl;
}
void test2()// 构造
{
vector<int> v = { 2,6,4,1,4,5,9,8 };
set<int> s(v.begin(), v.end());// set 支持 迭代区间的构造
for (auto i : s)
{
cout << i << " ";
}
cout << endl;
set<int> s1 = { 3,6,2,7,2,8,1 };// 支持 Initialist 构造
}
void test3()// 删除
{
set<int> s = { 3,6,2,7,2,8,1,5,4,9 };
s.erase(4);//删除val
for (auto i : s)
cout << i << " ";
cout << endl;
auto i = s.find(7);
s.erase(i); // 删除位置
for (auto i : s)
cout << i << " ";
cout << endl;
}
void test4()
{
//迭代器区间删除
set<int> s1 = { 10,20,30,40,50,60,70,80,90 };
auto itlow = s1.lower_bound(25);// >= 25 itlow指向30 大于等于指定值的第一个元素的迭代器。
auto itup = s1.upper_bound(60);// >60 itup指向70 查找第一个大于指定值的元素的位置
s1.erase(itlow, itup);
for (auto i : s1)// [30,70) 左闭右开
cout << i << " ";// 10 20 70 80 90
cout << endl;
}
int main()
{
//test1();
//test2();
//test3();
test4();
return 0;
}
*/
// multiset 底层也是 排序二叉树
// 允许冗余,只实现 排序操作
/*
#include<iostream>
#include<set>
#include<vector>
using namespace std;
int main()
{
multiset<int> s1 = { 1,3,5,5,4,2,1,3 };
for (auto i : s1)
cout << i << " ";//1 1 2 3 3 4 5 5
s1.erase(3);//默认查找 中序的第一个 key
return 0;
}
*/
//例题1: 找两个数组的交集 例2:找差集
//相等就是交集,记录下来,it1,it2++ 相等就是交集,直接跳过,it1,it2++
//不相等,it1,it2小的++,一个到尾就结束 不相等,录入小的,it1,it2小的++,一个到尾就结束
/*
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
set<int> s1(nums1.begin(), nums1.end());
set<int> s2(nums2.begin(), nums2.end());
vector<int>ans;
auto it1 = s1.begin(), it2 = s2.begin();
while (it1 != s1.end() && it2 != s2.end())
{
if (*it1 == *it2)
{
ans.push_back(*it1);
it1++, it2++;
}
else if (*it1 < *it2)
it1++;
else
it2++;
}
return ans;
}
*/
// map 是 key-value,模型
// 快速的查找功能,其内部实现通常基于红黑树 , 时间复杂度为O(log n)
// 1.快速查找:通过键来快速查找对应的值,可以有效加快数据查询的速度。
// 2.自动排序:map会根据键的大小自动对键值 key对进行排序,因此可以按顺序访问键值对。
// 3.唯一键:map中的键是唯一的,每个键只能对应一个值,可以确保数据的唯一性。
// 4.数据存储:可以用map来存储和管理键值对数据,提供了方便的数据组织方式。
// 5.字典:可以将map类比为字典,用键来索引值,方便进行数据管理和查找操作。
// key-value : key值不能修改,value可以修改
/*
#include<iostream>
#include<map>
#include<string>
using namespace std;
void test1()
{
//构造
map<string, string> dict;
pair<string, string> kv1("sort", "排序");
dict.insert(kv1);// 有名对象
dict.insert(pair<string,string>("left","左边"));//匿名对象
dict.insert(make_pair("right", "右边"));
//等价与上,使用 make_pair 构造 pair
dict.insert({ "String","字符串" });//隐式类型转换
map<string, string> dict2 = { {"String","字符串"},{"left","左边"} };//隐式类型转换 + Initializer_list
// iterator: key不能修改,value可以修改
// const_iterator: 都不能修改``
map<string, string>::iterator it = dict.begin();
while (it != dict.end())
{
cout << (*it).first << ":" << it->second << endl;
//cout << it.operator->()->first 编译器优化了
++it;
}
cout << endl;
for (auto& i : dict)//采用 引用减少复制
{
cout << i.first << ":" << i.second << endl;
}
}
void test2()
{
string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "香蕉","苹果","草莓", "苹果","草莓" };
map<string, int> countMap;
for (auto& e : arr)
{
//auto it = countMap.find(e);
//if (it != countMap.end())
//{
// it->second++;
//}
//else //第一次出现
//{
// countMap.insert({ e, 1 });
//}
countMap[e]++; //等价于上
//V& operator[](const K& key)
//{
// pair<iterator, bool> ret = this->insert(make_pair(key, V()));
// iterator it = ret.fisrt;
// return it->second;
//} !!!!!!!!!!!!!!!!! 返回 value 的引用 !!!!!!!!!!!!!!!
}
for (auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
//草莓:2 苹果:8 西瓜 : 3 香蕉 : 2
}
cout << endl;
// multimap 允许 key 冗余
multimap<int, string> sortMap;
for (auto& kv : countMap)
{
//sortMap[kv.second] = kv.first;// 草莓 被 香蕉 覆盖了 (使用 map_
sortMap.insert({ kv.second, kv.first });// key=2 重复,香蕉被 忽略了(使用 map)
}
cout << endl;
// multimap 和 map 一样,会对 key 进行自动排序
for (auto& kv : sortMap)
{
cout << kv.first << ":" << kv.second << endl;
}
cout << endl;
}
// [] 作用
void test3()
{
map<string, string> dict;
dict.insert({ "string","字符串" });
//插入
dict["right"];
//插入+修改
dict["left"] = "左边";
//查找
cout << dict["string"] << endl;
//修改
dict["right"] = "右边";
for (auto& i : dict)
{
cout << i.first << ":" << i.second << endl;
}
string str = "right";
cout << dict.count(str) << endl;
//打印 个数
}
int main()
{
//test1();
test2();
//test3();
return 0;
}
*/
简单的课堂笔记,去掉注释即可食用,注释什么的都在,诸君,加油!!!!!!!!!!