一、Set的介绍
1.1、Set相关文档介绍
cplusplus.com/reference/set/set/?kw=set
注意:1. 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。2. set中插入元素时,只需要插入value即可,不需要构造键值对。3. set中的元素不可以重复(因此可以使用set进行去重)。4. 使用set的迭代器遍历set中的元素,可以得到有序序列5. set中的元素默认按照小于来比较(升序)6. set中查找某个元素,时间复杂度为:log27. set中的元素不允许修改8. set中的底层使用二叉搜索树(红黑树)来实现
1.2、Set的使用
既然set是容器,那他也可以像前几个一样被构造。头文件#include<set>
1.空构造和拷贝构造
set<int> s1;
set<int> s2(s1);
2.迭代器构造
string s3("I love C++");
set<char> s4(s.begin(), s.end());
3.大于比较
set的底层是搜素二叉树,默认是小于排序(升序),也可是调成大于排序(降序)。set<int, greater<int>> s5;
容量接口:
修改接口:
这里我们对Set进行一些测试:
#include<iostream>
#include<set>
using namespace std;
void test1()
{
set<int> s1;
s1.insert(1); //插入操作
s1.insert(3);
s1.insert(5);
s1.insert(7);
s1.insert(4);
s1.insert(4);
s1.insert(5);
s1.insert(1);
set<int> s2(s1);
set<int>::iterator it = s1.begin();
for (auto e : s1)
{
cout << e << " "; // 1 3 4 5 7,是升序排列,别搞错了
}
cout << endl;
set<int>::iterator pos1 = find(s1.begin(), s1.end(), 5);
set<int>::iterator pos2 = s1.find(7); //set自带的查找函数
if (it != s1.end())
{
s1.erase(pos1); //删除5
s1.erase(pos2);
s1.insert(10);
s1.insert(20);
}
while (it != s1.end())
{
cout << *it << " "; //1 3 4 10 20
*it++;
}
cout << endl;
//删除指定区间
set<int>::iterator ret = s2.find(5);
s2.erase(s2.begin(), ret);
for (auto e : s2)
{
cout << e << " "; //5 7
}
cout << endl;
//寻找是否有val,找到返回1
if (s2.count(5)) // s2中有5就返回1,进入循环
{
cout << "s2中有5:" << endl; //s2中有5
}
cout << s2.empty() << endl; // 判空
cout << s1.size() << endl; //s1的个数是5
cout << s2.size() << endl; //s2的个数是2
}
int main()
{
test1();
}
二、multiset 的介绍
2.1、multiset相关文档介绍
cplusplus.com/reference/set/multiset/?kw=multiset
注意:
1. multiset中再底层中存储的是<value, value>的键值对2. mtltiset的插入接口中只需要插入即可3. 与set的区别是,multiset中的元素可以重复,set是中value是唯一的4. 使用迭代器对multiset中的元素进行遍历,可以得到有序的序列5. multiset中的元素不能修改6. 在multiset中找某个元素,时间复杂度为O(log2)7. multiset的作用:可以对元素进行排序
2.2、multiset的使用
multiset的count和erase跟set相比有很大区别:
1、set.count(val)是如果找到val就返回1;因为multiset的数可以重复,multiset.count(val)找到val后返回multiset中有几个val。
2、set.erase(val)是找到要删除的val后,返回1;multiset.erase(val)找到要删除的val后返回val有几个,并且全删val。
这里我们对multiset进行一些测试:
void test2()
{
multiset<int> multiset;
multiset.insert(4);
multiset.insert(5);
multiset.insert(2);
multiset.insert(1);
multiset.insert(1);
multiset.insert(3);
multiset.insert(3);
multiset.insert(3);
for (auto e : multiset)
{
cout << e << " ";
}
cout << endl;
set<int> set(multiset.begin(), multiset.end());
cout << multiset.erase(1) << endl;//2 返回删除的1的个数
for (auto e : multiset)
{
cout << e << " "; //2 3 3 3 4 5
}
cout << endl;
cout << set.erase(4) << endl;//1 返回一个bool值,存在删除的值返回1
for (auto e : multiset)
{
cout << e << " "; //2 3 3 3 4 5
}
cout << endl;
auto pos1 = multiset.find(3); //返回中序的第一个3的迭代器
while (pos1 != multiset.end())
{
cout << *pos1 << " ";//3 3 3 4 5
pos1++;
}
}
三、Map的介绍
3.1、Map相关文档介绍
cplusplus.com/reference/map/map/?kw=map
3.2、Map的使用
#include<iostream>
#include<map>
using namespace std;
int main()
{
map<string, int> m;//创建一个map对象m
//向m中插入pair
map<string, int> m1(m.begin(), m.end);//用m的区间构造m1
map<string, int> m2(m1);//用m1拷贝构造m2
return 0;
}
注意:在元素访问时,有一个与operator[ ]类似的操作at()(该函数不常用)函数,都是通过key找到与key对应的value然后返回其引用,不同的是:当key不存在时,operator[ ]用默认value与key构造键值对然后插入,返回该默认value,at()函数直接抛异常。
map可以用[ ]进行访问(不是下标访问,一定要注意)mapped_type& operator[] (const key_type& k);
具体实现如下:
mapped_type& operator[] (const key_type& k) { return (*((this->insert(make_pair(k, mapped_type()))).first)).second; }
这个如果不好理解的话,看一下下面这个:
mapped_type& operator[] (const key_type& k) { //1、调用insert返回迭代器区间 pair<iterator, bool> ret = insert(make_pair(k, mapped_type())); //2、利用ret调用value值 return ret.first->second;//return (*(ret.first)).second; }
- 首先调用insert函数插入键值对返回迭代器ret
- 通过返回的迭代器ret调用元素值value。
在这里我们又分两种情况去处理:
1、如果k在map对象中,则插入失败,返回的bool类型为false,返回的迭代器为k所在结点的迭代器,而迭代器解引用*(ret.first)获得的就是pair,最后再通过pair访问到value值,整体可优化成ret.first->second,这里返回引用的好处为查找k对应v,修改k对应v。
2、如果k不在map对象中,则插入成功,返回的bool类型为true,返回的迭代器为新插入的k所在结点的迭代器位置,接着调用ret.first获得pair的迭代器,再通过->second获得value,这里返回引用的好处为插入和修改。
void test_map1()
{
map<string, string> dict;
//dict.insert(pair<string, string>("sort", "排序"));
dict.insert(make_pair("sort", "排序"));
dict.insert(make_pair("string", "字符串"));
dict.insert(make_pair("count", "计数"));
//map<string, string>::iterator dit = dict.begin();
auto dit = dict.begin();
while (dit != dict.end())
{
cout << (*dit).first << ":" << (*dit).second << endl;
++dit;
}
cout << endl;
}
void test_map2()
{
map<string, string> dict;
//dict.insert(pair<string, string>("sort", "排序"));
dict.insert(make_pair("sort", "排序"));
dict.insert(make_pair("string", "字符串"));
dict.insert(make_pair("count", "计数"));
dict.insert(make_pair("string", "(字符串)")); // 插入失败
dict["left"]; // 插入
dict["right"] = "右边"; // 插入+修改
dict["string"] = "(字符串)"; // 修改
cout << dict["string"] << endl; // 查找
cout << dict["string"] << endl; // 查找
//map<string, string>::iterator dit = dict.begin();
auto dit = dict.begin();
while (dit != dict.end())
{
//cout << (*dit).first << ":" << (*dit).second << endl;
cout << dit->first << ":" << dit->second << endl;
++dit;
}
cout << endl;
}
void test_map3()
{
string arr[] = { "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉", "梨" };
map<string, int> countMap;
//for (auto& e : arr)
//{
// auto ret = countMap.find(e);
// if (ret == countMap.end())
// {
// countMap.insert(make_pair(e, 1));
// }
// else
// {
// ret->second++;
// }
//}
for (auto& e : arr)
{
countMap[e]++;
}
for (auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
}
//V& operator[](const K& key)
//{
// pair<iterator, bool> ret = insert(make_pair(key, V()));
// return ret.first->second;
//}
int main()
{
test_map1();
test_map2();
test_map3();
return 0;
}
四、multiset的介绍
4.1、multiset相关文档介绍
注意: multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以重复的。
4.2、multimap的使用
1、map中的valuevalue是唯一的,不允许重复。multimap可以。
2、multimap中没有[ ]。因为它的key和value是一对多的关系,比如上面的苹果,那key是苹果,但是苹果出现了好几次,每一个都有一个value,那他到底返回哪一个呢?为啥map能返回呢,因为在map中每一个key(苹果)都对应一个自己的value,所以每次返回一个value.但是multimap是一个key有好几个value.
void test7()
{
multimap<string, string> mlp1;
mlp1.insert(make_pair("one", "一"));
mlp1.insert(make_pair("two", "二"));
mlp1.insert(make_pair("three", "三"));
mlp1.insert(make_pair("four", "四"));
mlp1.insert(make_pair("four", "四"));
mlp1.insert(make_pair("spring", "五"));
mlp1.insert(make_pair("spring", "五"));
for (auto e : mlp1)
{
cout << e.first << ":" << e.second << endl;
}
}
int main()
{
test7();
}