一、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); //删除5s1.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,找到返回1if (s2.count(5)) // s2中有5就返回1,进入循环{cout << "s2中有5:" << endl; //s2中有5}cout << s2.empty() << endl; // 判空cout << s1.size() << endl; //s1的个数是5cout << 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值,存在删除的值返回1for (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 5pos1++;}
}
三、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中插入pairmap<string, int> m1(m.begin(), m.end);//用m的区间构造m1map<string, int> m2(m1);//用m1拷贝构造m2return 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();
}