前言
我们知道C++的STL库,不只是向我们提供了vector,string,list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和数据结构操作。vector封装了数组,list封装了链表,map和set封装了二叉树,在这些容器中,都会提供基础的操作:增加,删除,排序,查找等。
1、set
map和set都是关联性容器,他的特点是增加或者删除对迭代器的影响都很小,除了操作的节点,对其他节点几乎没什么影响
set是用来存储同一类型的数据,里面的元素都只有一个key值,他支持高效的关键字查询和插入操作,比如检查一个关键字是否在set中。如果这个key值之前就存在,那就不进行插入。
以下是关于map和set的常用函数,这里给出插入,查找和删除的方法:
插入insert:
set<int> s;
s.insert(1);
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(3);
s.insert(4);
for (auto e : s)
{
cout << e << " ";
++e;
}
cout << endl;
//或者你可以采用一下输出方式
//set<int> iterator::it;
//for(it=s.begin();it!=s.end();it++)
//{
// cout<<*it<<" ";
//}
// cout<<endl;
运行截图:
可以看到set的插入操作是排序+去重
查找Find:
set<int>::iterator pos = s.find(3);
if (pos != s.end())
{
cout << "找到啦!"<<endl;
}
运行截图:
删除erase:
s.erase(pos);
cout << "删除后:" << endl;
for (auto e : s)
{
cout << e << " ";
++e;
}
cout << endl;
截图:
清空clear:
s.clear();
for (auto e : s)
{
cout << e << " ";
++e;
}
截图:
2、map
map和set一样都是关联式容器,他们的底层容器都是红黑树,区别就在于map的值不作为键,键和值是分开的
插入Insert
map<string, string> m;
m.insert(make_pair("Apple", "苹果"));
m.insert(make_pair("Pair", "梨"));
m.insert(make_pair("Right", "右边"));
//m.insert(make_pair("Right", "正确"));
m.insert(make_pair("Banana", "香蕉"));
m.insert(make_pair("Orange", "橘子"));
m.insert(make_pair("Grap", "葡萄"));
for(map<string,string>::iterator e=m.begin();e!=m.end();e++)
{
cout << e->first << ":" << e->second << endl;
}
cout << endl;
查找Find
it = m.find("Banana");
if (it != m.end())
{
cout << "找到了!该单词的中文是:" << it->second << endl;
}
else
{
cout << "没有找到!";
}
cout << endl;
删除erase
m.erase(it);
cout << "删除刚找到的元素后,剩余的元素为:" << endl;
map<string, string>::iterator e1;
for (e1 = m.begin(); e1 != m.end(); e1++)
{
cout << e1->first << ":" << e1->second << endl;
}
3、map和set的区别
set特性如下:
- set是以RBTree作为底层容器
- 所得元素的只有key没有value,value就是key
- 不允许键值重复
- 所得的元素都会自动排序+去重
- 不能通过迭代器来改变set的值
map特性如下:
- map以RBTree作为底层容器
- 所有的元素都是以键+值存在
- 不允许键重复
- 所有元素通过键都会自动排序
- map的键是不能修改的,但是其键对应的值是可以修改的
关于map和Set的简单应用,这里贴出一个连接,是统计水果出现的次数,并且统计出前topk中最喜欢的水果统计水果次数
4、multiset和multimap
multiset的中文名是多重集合
其实就是集合的扩展版,不同的是在set中,一个值只能出现一次,而在多重集合中,一个值可以出现多次。并且插入和删除一个数都能够在O(logN)的时间内完成,它能够保证序列中的数是有序的。
multimap和map所支持的操作相同(除了multimap不支持下标操作),multimap允许重复的元素。以下是演示multimap的常用接口的代码:
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
///1. 初始化
multimap<int, string> mapStudent;
multimap<int, string>::iterator iter, beg, end;
///2. 添加元素
///multimap不支持下标操作
mapStudent.insert(pair<int, string>(0, "student_one"));
mapStudent.insert(pair<int, string>(0, "student_one_copy"));///一对多
mapStudent.insert(pair<int, string>(1, "student_two"));
mapStudent.insert(pair<int, string>(5, "Fear Kubrick"));
mapStudent.insert(pair<int, string>(2, "Akemi Homura"));
mapStudent.insert(pair<int, string>(-1, "Eren Jaeger"));
mapStudent.insert(pair<int, string>(99, "lin"));
cout << mapStudent.size() << endl;
cout << endl;
///3. 遍历
for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
cout << iter->first << " " << iter->second << endl;
cout << endl;
///4. 单键查询与范围查询
///单键查询
int count = mapStudent.count(0);
iter = mapStudent.find(0);
for (int i = 0; i < count; i++, iter++)
cout << iter->first << " " << iter->second << endl;
cout << endl;
///范围查询
beg = mapStudent.lower_bound(1);/// >=1
end = mapStudent.upper_bound(5);/// <=5
for (; beg != end; beg++)
cout << beg->first << " " << beg->second << endl;
cout << endl;
///5. 删除
iter = mapStudent.find(1);
mapStudent.erase(iter);
cout << mapStudent.size() << endl;
for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
cout << iter->first << " " << iter->second << endl;
cout << endl;
///6. 判空与清空
if (!mapStudent.empty())
mapStudent.clear();
}