1、它是一种模板类型的结构体,定义在头文件#include<utility>
template<class T1,class T2>
2、有两个成员是first,second
3、模板参数可以是任何类型的
1、分为序列式容器和关联式容器
1)序列式容器就是里面操作的数据无关联,比如:vector,它的操作push,pop
2)关联式容器就是里面操作的数据有关联,比如:set,map,它的操作insert,erase
*set是一种Key结构,它的元素就是它的键值,它的键值唯一,不允许重复,它里面的数都会被自动排序。
*它也是模板类型的:
template < class T,class Compare = less<T>, class Alloc = allocator<T> > class set;
1)第一个参数是键值类型
2)第二个模板参数可以利用仿函数实现,这样我们就可以控制在set中插入值的时候是按什么顺序进行排列的
3)第三个参数是空间配置器
1)插入到set中的值是排好序的
2)如果重复进行插入的话,set是会把重复的值过滤掉的(防冗余)
它在底层是利用红黑树进行实现的,但注意它的底层插入机制是insert_unique
三种类型:
A:直接插入一个值:pair<iterator,bool> insert ( const value_type& x );B:在特定的位置插入一个值:iterator insert ( iterator position, const value_type& x );C:插入一段区间:template <class InputIterator>void insert ( InputIterator first,InputIterator last);
用代码简单使用:
void TestSet(){ //插入的测试 //1、直接插入一个值 set<int> s1; s1.insert(1); s1.insert(2); s1.insert(3); s1.insert(4); s1.insert(5); //2、在特定的位置进行插入 /*s1.insert(s1.begin(),10); s1.insert(s1.begin(),5); s1.insert(s1.begin(),7); s1.insert(s1.begin(),9);*/ //3、插入一段区间 //s1.insert (s1.begin(),s1.end()); set<int>::iterator it1 = s1.begin(); while(it1 != s1.end()) { cout<<*it1<<" "; it1++; } cout<<endl;}2)erase
三种类型:
A:删除特定位置的值:void erase ( iterator position );B:删除一个值:size_type erase ( const key_type& x );C:删除一段迭代器区间:void erase ( iterator first, iterator last );
用代码简单使用:
void TestSet(){ //插入的测试 //1、直接插入一个值 set<int> s1; s1.insert(1); s1.insert(2); s1.insert(3); s1.insert(4); s1.insert(5); //2、在特定的位置进行插入 /*s1.insert(s1.begin(),10); s1.insert(s1.begin(),5); s1.insert(s1.begin(),7); s1.insert(s1.begin(),9);*/ //3、插入一段区间 //s1.insert (s1.begin(),s1.end()); //删除的测试 //1、直接删除值 //说明:删除这个值得时候,如果不在你原本的插入数据中时,不会发生崩溃 /*s1.erase(4); s1.erase(1); s1.erase(6);*/ //2、删除一个特定位置的值 //说明:如果是删除一个位置上的数的话,如果没有这个数的话,删除的话 // 就会崩溃 //set<int>::iterator pos = s1.find(6); //s1.erase(pos); //3、删除一段迭代器区间 //s1.erase(++s1.begin(),--s1.end()); set<int>::iterator it1 = s1.begin(); while(it1 != s1.end()) { cout<<*it1<<" "; it1++; } cout<<endl;}说明:要注意的点我在上面的测试代码中已经说明。3)count:
判断一个值是否存在,存在的话返回1,不存在返回0
//如果要查找值是否存在,那么可以用find先进行查找,然后再进行 //判断是否存在 map<string,int>::iterator it1 = countstr.find(1); if(it1 != countstr.end()) {} else {} //而如果用count的话,因为它的意义。我们可以直接来进行判断 if(countstr.count(key) > 0) {} else {}4)emplace:
c++11新特性:
说明:用于插入一个元素,比insert的效率高一些, insert插入的时候返回是先进行构造一个临时对象,然后通过这个临时对象再进行拷贝构造,而emplace是直接就进行的构造,效率更高一些
简单使用:
set<string> s2; s2.emplace("hello"); auto ret = s2.emplate("hello"); if(!ret.second) cout<<"hello 已经存在"<<endl;5)find:
iterator find(const value_type& val) const;
如果找到的话就返回这个位置的迭代器,否则就返回end。
6、应用:
1)因为set里有检查值是否存在的接口count,因此我们可以使用set来进行单词拼写的检查
2)插入的时候有防冗余的作用,可以用于过滤,我们可以用其实现爬虫
二、map(映射)
1、概念:
*map是一种key(键值)-value(实值)结构;
它的每一种键值对应它的实值。
它有键值和实值,它的键值是不允许更改的,但是它的实值是可以不同的。
map中的所有元素都是pair,pair的first被视为键值,它的second被视为实值。
(map的每个元素都是pair类型。typedef pair<K,V> value_type;)
*它也有和set类似的模板结构
template<class Key,class T,classCompare=less<Key>,class Alloc=allocator<pair<const Key,T> > >它有四个模板参数类型,第一个是键值的类型。第二个是实值的类型。第三个是一个仿函数,它传入的是键值的比较方式,默认是升序排列。第四个是空间配置器。
2、底层实现:
也是通过红黑树进行实现的
3、一些常用接口的简介
1)insert:
三种类型:
*pair<iterator,bool> insert(const value_type& val); 说明: 插入一个value_type类型,返回值是一个pair类型。 pair<iterator,bool>=pair<map<K,V>::iterator,bool>。如果插入成功的话则bool就为true,且iterator指向插入的位置,否则的话iterator就指向已经存在的这个元素的位置。iterator是一个pair<K,V>类型的迭代器。 *iterator insert(iterator,const value_type& val) 在一个迭代器的位置插入一个value_type类型的数据,如果插入成功的话返回这个成功位置的迭代器,如果失败的话则返回这个传入的迭代器。
*template<class InputIterator> void insert(InputIterator first,InputIterator last); 插入一段迭代器区间
2)erase:
*void erase(iterator position) 删除一个这个迭代器位置的元素。 *size_type erase(const key_type& k) 删除这个键值所在的位置,成功返回1,失败返回0 *void erase(iterator first,iterator last); 删除一段迭代器区间。
3)find:
iterator find(const key_type& k) 如果查找成功的话则返回这个元素的迭代器,否则返回end,所以在使用find返回的迭代器之前要先判断一下。4)count:
size_type count(const key_type& k)const 与set的count功能一样。
5)Operator[]
mapped_type& operator[](const key_type& k) map中的operator[]是最常用的,如果map中有这个k,则它就把这个k所对应的value的引用返回。如果map中没有这个k的话,则它会调用insert(pair<K,V>(k,V())),将k和V的缺省值对应起来插入进去,并返回这个value的引用。模拟实现下重载下标操作符:
V& operator[](const K& key) { pair<iterator,bool> ret = insert(const K& key,const V& value); return ret->first.second; }3、应用:
1)通常用来实现字典结构
2)统计字符串出现的个数等等
三、multiset和multimap简单说明
1、multiset:
1)接口和set类似
2)要说明的:
**multiset的插入是不防冗余的,插入的原则就是中序遍历之后是有序即可
**multiset要是要查找一个重复插入的值的话,它找到的是这些重复数的第一个。
#include<iostream>//#include<multimap>#include<set>using namespace std;void TestMultimap(){ multiset<int> m2; m2.insert(1); m2.insert(2); m2.insert(3); m2.insert(2); m2.insert(5); multiset<int>::iterator it2 = m2.find(2); cout<<*it2<<endl; it2++; cout<<*it2<<endl; it2++;};int main(){ TestMultimap(); return 0;}2、multimap:
1)key可以相同,但是value可以不同,这是要和map进行区别的一点
2)它没有重载下标运算符[]
3)它里面的count是真正意义上的进行统计个数,因为它也是不防冗余的,而在set和map中,count其实就只是充当找这个值是否存在。
四、一些要说的琐碎之话:
1、关于空间适配器和容器的区别
适配器说白了就是用于转换。我用下面的栈和map举个例子来说明下:
1)stack和queue是适配器
2)map和set是容器
新闻热点
疑难解答