set
set是key模型,属于关联式容器,并非序列式容器,数据之间有非常大的关联关系,所以不是像序列式容器一样头尾随便插,所以不用push这个概念了,而是采用insert按照关联规则进行插入。
set的功能不是单纯的排序,还具有去重的功能。
int main()
{
set<int> s1;
s1.insert(1);
s1.insert(3);
s1.insert(2);
s1.insert(7);
s1.insert(2);
s1.insert(6);
s1.insert(1);
s1.insert(3);
s1.insert(8);
s1.insert(5);
s1.insert(0);
set<int>::iterator it = s1.begin();
while (it != s1.end())
{
//*it+=1;//set的底层式平衡搜索二叉树,是不允许修改key的,因为这样会破坏搜索二叉树的结构
cout << *it << " ";
it++;
}
//判断x在不在set容器里面
int x;
while (cin >> x)
{
//方法一
/* auto ret = s1.find(x);
if (ret != s1.end())
{
cout << "在" << endl;
}
else
{
cout << "不在" << endl;
}*/
//方法二
if (s1.count(x))//count是用来返回x值在容器当中的个数,但是再set模型中显得感觉有些鸡肋。其实count的作用再multiset容器中才更适用。
{
cout << "在" << endl;
}
else
{
cout << "不在" << endl;
}
}
return 0;
}
multiset
插入的时候允许键值冗余,所以式单纯的排序,不报错去重。
int main() { multiset<int> s1; s1.insert(1); s1.insert(3); s1.insert(2); s1.insert(7); s1.insert(2); s1.insert(6); s1.insert(1); s1.insert(3); s1.insert(8); s1.insert(5); s1.insert(0); multiset<int>::iterator it = s1.begin(); while (it != s1.end()) { //*it+=1;//set的底层式平衡搜索二叉树,是不允许修改key的,因为这样会破坏搜索二叉树的结构 cout << *it << " "; it++; } }
如何实现这种冗余插入呢?其实相同的值也一样插入,再该值的左边或者右边都可以。
int main() { multiset<int> s1; s1.insert(1); s1.insert(3); s1.insert(2); s1.insert(7); s1.insert(1); s1.insert(6); s1.insert(1); s1.insert(3); s1.insert(8); s1.insert(1); s1.insert(8); s1.insert(8); s1.insert(0); set<int>::iterator it = s1.begin(); //当有多个key时,找中序排列的第一个key,比如说按照搜索二叉树的规则来进行比较大小找到第一个key,如果有多个相同的key并不是直接选择这个key,而是继续向左子树找最左边的key,所以也可以理解为找中序的第一个key //下面也可以印证这个说法 auto ret = s1.find(1); while (ret != s1.end() && *ret == 1) { cout << *ret << " "; ret++; } }
![]()
map
map时key/value模型
int main() { map<string, string> dict; dict.insert(pair<string,string>("left", "左"));//传统的写法时喜欢插入pair的匿名构造函数 dict.insert(make_pair("front", "前"));//但是我们更喜欢用make_pair模板函数,其实先也是调用pair的匿名构造来return,但是优势是可以不用传模板参数,函数自己来推导 dict.insert(make_pair("right", "右")); dict.insert(make_pair("behind", "后")); dict.insert(make_pair("behind", "后面"));//该行代码插入失败,因为搜索二叉树中value不会参与搜索的规则,只管key值,key值已经有了所以插入失败。 dict["string"] = "(字符串)"; //修改,该行代码可以成功修改string对应的value dict["sounth"]; // 插入,而south的value是没有办法显示给的,只能给valud的默认构造也就是string的默认构造就是一个空串 dict["north"] = "右边"; // 插入并且可以通过这种方式给value cout << dict["string"] << endl; // 对于已存在map里面的key是查找对应的value cout << dict["west"] << endl; // 对于不存在在map里面的key返回空串 auto dit = dict.begin(); while (dit != dict.end()) { cout << (*dit).first << ":" << (*dit).second << endl;//不能写成cout<<*dit<<" ",因为*dit返回的是一个结构pair,而pair并不支持流插入 cout << dit->first << ":" << dit->second << endl;//上面一行时通过c++运算符重载*来解引用数据,而c++也重载了符号->。dic调用operator时返回的时数据的地址pair<stinr,string>*,由此可以编译器在这里省略了一个箭头,也可以理解成优化掉了。 ++dit; } cout << endl; }
![]()
map的[ ]运算符重载
int main()
{
string arr[] = { "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉", "梨" };
map<string, int> countMap;
//统计次数的传统写法
//for (auto& e : arr)//加上引用,避免走string的深拷贝
//{
// auto ret = countMap.find(e);
// if (ret == countMap.end())
// {
// countMap.insert(make_pair(e, 1));
// }
// else
// {
// ret->second++;
// }
//}
//现代的写法:一行代码统计次数
for (auto& e : arr)
{
countMap[e]++;//能这样写的原因再下面,原因在下面。[]的功能:
//1、插入,e不存的话我直接插入,只是mapped_type()采用的是默认构造
//2、返回值mapped_type类型变量的引用,你可以用来查找也可以进行充型赋值修改数据
}
for (auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
return 0;
}
//
mapped_type& operator[] (const key_type& k)
{
return (*((this->insert(make_pair(k, mapped_type()))).first)).second
}
//翻译一下
mapped_type& operator[] (const key_type& k)
{
pair<iterator, bool> ret = insert(make_pair(k, mapped_type()));z//insert的返回值是一个pair结构体,其中的第二个参数second是bool值,表述插入是否成功,插入成功就是true否则就是false。第一个参数是一个迭代器,指向新插入的元素或者和key相等的元素。在这里插入的元素是(k,mapped_type()),而mapped_type在这里是int类型,用来统计水果的个数,所以这里调用的mapped_type()就是int类型的默认构造,也就是0。
return ret.first->second;//ret是一个pair<iterator, bool>,ret.first就是一个迭代器,迭代器指向插入的元素的位置,它的second就是统计的个数
//当水果第一次出现的时候,成功插入(“水果”,0),返回当前水果再map中的位置iterator的second也就是次数0。当水果已经存在与map当中的时候,就插入失败,返回当前已存在map当中水果的位置iterator的second也就是水果之前出现的次数。
}
multimap
允许键值冗余,但是没有了[ ]运算符重载。因为现在key和value的关系是一对多了,而[ ]运算符重载的核心功能是查找key对应的value,找到了可以对改值进行获取甚至修改。
int main() { multimap<string, string> mdict; mdict.insert(make_pair("sort", "排序")); mdict.insert(make_pair("string", "字符串")); mdict.insert(make_pair("count", "计数")); mdict.insert(make_pair("string", "(字符串)")); // 插入成功 mdict.insert(make_pair("string", "字符串")); for (auto& kv : mdict) { cout << kv.first << ":" << kv.second << endl; } return 0; }