使用关联式容器:
1、关联式容器(associative)又称“联合容器”,将值(value)和关键字(keyword)成对关联,举例来说,在学生管理系统设计时,可以将学号作为关键字,起索引的目的,而将学生姓名、性别、籍贯等信息作为值与学号配对。
2、标准的STL提供了4种联合容器类模板:set、map、multiset和multimap,总体来说,set中仅仅包含关键字,而没有值的概念,map中存储的是“关键字——值”对,map和set中不会出现多个相同的关键字,multiset和multimap可以分别看作是对set和map的扩展,multimap和multiset允许相同关键字的存在。
3、4种关联式容器都会根据指定的或默认的排列函数,以关键字为索引,对其中的元素进行排序。
1、使用set容器必须#include <set>。
2、其使用形式如下:
set<存储类型 [,排序函数或对象] > 容器对象名;
第1个参数用以指定存储类型,第2个参数是可选的,用来指定对关键字进行排序的函数或函数对象(函数对象后面介绍),在默认情况下,将使用less<>函数模板,字面意义上可理解为按从小到大进行排列。可以自己设定排序方式:
set<int, greater<int> >
3、根据set的特点,STL提供了3种创建set的方式:
——创建空set容器对象,如:
set<int> obS;
——将迭代器的区间作为参数的构造函数,如:
int sz[9]={1,2,3,4,5,6,3,5,6};
set<int> A(sz,sz+9);
——根据已有同类型的容器创建新容器,如
set<int> B(A);
4、set不支持[]下标式的随机访问,必须通过迭代器访问元素。
#include <iostream>
#include <set>
using namespace std;
int main()
{
int arr[9]={2,1,3,5,4,6,3,5,6};
set<int> setInt(arr,arr+9);
cout<<"setInt's size:"<<setInt.size()<<endl;
set<int> :: iterator it;
for(it = setInt.begin();it != setInt.end();++it) //默认从小到大排序
cout<<*it<<" ";
cout<<endl;
set<int,greater<int> > setInt1(arr,arr+9); //这里greater后面尖括号要分开点,定义从大到小排序
set<int,greater<int> > ::iterator it1; //可以同用一个迭代器指针,也可以单独在定义
cout<<"setInt's size:"<<setInt.size()<<endl;
for(it1 = setInt1.begin();it1 != setInt1.end();++it1)
cout<<*it1<<" ";
cout<<endl;
return 0;
}
|
#include <iostream>
#include <set>
using namespace std;
class Point
{
private:
int _ix;
int _iy;
public:
Point(int ix=0,int iy=0):_ix(ix),_iy(iy)
{}
int multiply()const
{
return _ix*_iy;
}
friend ostream & operator << (ostream & os,const Point & rhs);
};
ostream& operator << (ostream& os,const Point & rhs)
{
os<<"("<<rhs._ix<<","<<rhs._iy<<")";
return os;
}
bool operator > (const Point & lhs,const Point & rhs)
{
return lhs.multiply() > rhs.multiply();
}
int main()
{
Point arr[4] = {Point(1,2),Point(3,4),Point(-1,2),Point(4,5)};
//自定义排序函数
set<Point,greater<Point> > setPoint(arr,arr + 4); //前面重写了>
set<Point,greater<Point> >:: iterator it;
for(it = setPoint.begin(); it != setPoint.end(); ++it)
cout<< *it <<" ";
cout<<endl;
return 0;
}
|
multiset容器:
1、使用multiset需要包含头文件#include<set>。
2、multiset的创建方式与set相同,也是3种方式。
3、multiset与set不同之处在于其允许出现相同的关键字。
用法就 set换成了multiset
#include <iostream>
#include <set>
using namespace std;
int main()
{
int arr[9]={2,1,3,5,4,6,3,5,6};
multiset<int,greater<int> > ms(arr,arr+9); //从大到小
cout<<"ms's size:"<<ms.size()<<endl;
multiset<int>:: iterator it;
for(it = ms.begin();it != ms.end();++it)
cout<<*it<<" ";
cout<<endl;
return 0;
}
|
map容器:
1、使用map必须包括头文件#include <map>。
2、map的元素是一对对的“关键字——值”组合,“关键字”用于搜寻,而“值”用来表示我们要存取的数据。
3、在map容器中,每个关键字只能出现一次,不能重复。
4、可使用模板类pair<class T1,class T2>来表示map容器中形如“关键字-值”的每个元素。如下述语句就生成了map容器对象的一个元素t:
pair<const int, string> t(600036,”招商银行”);
cout << t.first << t.second << endl;
//t.first表示600036,t.second表示,”招商银行”
|
5、也可创建pair<class T1,class T2>的匿名元素:
pair<const int, string>(600036,”招商银行”); |
6、const表示关键字是只读的。
7、创建map容器对象的格式如下,各参数含义和set的类似:
map<关键字类型,值类型[,排序函数或对象]> 容器对象名;
8、创建方式也是3种:
——创建空map容器对象,如:
map<int,string> obM;
——将迭代器的区间作为参数的构造函数,如
pair<int,string> sz[4]={
pair<int,string>(1,”北京”),pair<int,string>(2,”深圳”),
pair<int,string>(3,”广州”),pair<int,string>(2,”苏州”)};
map<int,string> obM(sz,sz+4);
——根据已有同类型的容器创建新容器
map<int,string> B(A);
10、map支持[]下标式的随机访问,也支持迭代器访问元素。
//map第一个元素是key,可以通过key直接访问第二个元素的值:
maptmp[2]="hello";
maptmp["22"]=123;……
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<string,string> map1;
map1["11"] = "aa";
map1["22"] = "bb";
map1["33"] = "cc"; //没有相同关键字的时候直接添加
map1["33"] = "dd"; //有相同关键字就直接覆盖
for(auto & elem : map1)
{
cout<< elem.first <<"-->"<< elem.second<<endl;
}
return 0;
}
|
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
pair<int,string> t(600036,"招商银行");
cout<< t.first <<"-->"<< t.second <<endl;
cout<<endl;
pair<int,string> pair1[4] =
{
pair<int,string> (1,"北京"),
pair<int,string> (2,"深圳"),
pair<int,string> (3,"广州"),
pair<int,string> (2,"天津"),
};
//map里面不允许有相同关键字的pair元素
map<int,string> map1(pair1,pair1+4);
map1[5]="昆明";
map<int,string>::iterator it;
for(it = map1.begin();it != map1.end();++it)
{
cout<< it->first <<"-->"<< it->second <<endl;
}
cout<<endl;
//map可以用下标访问
cout<< "2:"<<map1[2]<<endl;
return 0;
}
|
#include<iostream>
#include<map>
#include<string>
using namespace std;
int main()
{
pair<int,string> arr[4] =
{
pair<int,string> (1,"北京"),
pair<int,string> (2,"深圳"),
pair<int,string> (3,"广州"),
pair<int,string> (2,"天津"),
};
//multimap里面允许有相同关键字的pair元素
multimap<int,string> map1(arr,arr+4);
for(auto& elem:map1)
cout<<elem.first<<" "<<elem.second<<endl;
cout<<endl;
//map1[5] = "昆明"; // multimap不支持随机访问
pair<int,string> p1(5,"昆明");
map1.insert(p1);
for(auto& elem:map1)
cout<<elem.first<<" "<<elem.second<<endl;
cout<<endl;
return 0;
}
|
multimap容器:
1、multimap与map的关系,类似于multiset与set的关系,使用multimap同样需要包含头文件<map>,multimap的创建方式与map相同,有3种方式。multimap与map不同之处在于其允许出现相同的元素。此时不支持[]随机操作。
用法就 map 换成了 multimap
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
pair<int,string> pair1[4] =
{
pair<int,string> (5,"北京"),
pair<int,string> (9,"上海"),
pair<int,string> (2,"广州"),
pair<int,string> (7,"深圳"),
};
//默认从小到大,按关键字来排序
multimap<int,string> map1(pair1,pair1+4);
multimap<int,string>::iterator it;
for(it = map1.begin();it != map1.end();++it)
{
cout<< it->first <<"-->"<< it->second <<endl;
}
cout<<endl;
//设置从大到小来排序
multimap<int,string,greater<int> > map2(pair1,pair1+4);
//在vs里面要用greater要加上#include <functional>
for(it = map2.begin();it != map2.end();++it)
{
cout<< it->first <<"-->"<< it->second <<endl;
}
return 0;
}
|
关联式容器支持的成员函数操作:
和序列式容器一样,关联式容器同样支持插入、删除及元素的查找和访问等通用操作
元素的插入:
在下面的4种insert函数中,ob代表关联式容器对象名,t对set和multiset来说,是个关键字,而对map和multimap来说,是个pair结构。
1. pair<iterator, bool> ob.insert(t)
适用于map和set容器。返回一个pair<iterator,bool>值,当ob中不包含t时,将t插入ob中,bool为true;否则不进行插入,bool为false。无论是否进行了插入操作,iterator都指向关键字和t相同的元素。
2. iterator ob.insert(t)
适用于multiset和multimap,将t插入到ob中,并返回指向t所在位置的迭代器。
3. iterator ob.insert(p,t)
从迭代器p开始搜索应将t插入到ob中的位置。
对于set/map,只有当ob中不包含t时才进行插入。无论是否插入,都返回一个指向t关键字的iterator。
对于multiset/multimap,将t插入到ob中,返回指向t的iterator;p的作用是加快查找速度。
4. void insert(i, j)
i,j是一对输入迭代器,此函数用于将[i,j)区间的元素插入到ob中。
|
元素的删除:
关联式容器支持以下4种删除元素的方式:
(1)int ob.erase(keyword)
删除容器ob中所有关键字为keyword的元素,返回删除元素的个数。
(2)void ob.erase(p)
从ob中删除迭代器p所指向的元素,p必须存在,且不能为ob.end(),因为ob.end()是最后一个元素的下一个位置,并不真正存在。
(3)void ob.erase(q1,q2)
从ob中删除半开区间[q1,q2)之间的所有元素。
(4)void clear(void)
删除ob中的所有元素,等价于void ob.erase(ob.begin(), ob.end());
|
#include<iostream>
#include<set>
#include<map>
#include<string>
using namespace std;
int main()
{
pair<int,string> arr[2] =
{
pair<int,string>(1,"A"),
pair<int,string>(2,"B")
};
// 创建待插入元素
pair<int,string> t1(3,"C");
map<int,string> map1(arr,arr+2);
for(auto& elem:map1)
cout<<elem.first<<","<<elem.second<<endl;
// map不允许关键字相同,所以有插入成功和不成功的说法
// 成功bool=1,失败bool=0
// 插入不管成功与否,map中都会存在要插入的pair,所以返回值会返回这个要插入的pair在map中的位置
// insert的第一个返回类型是一个对应的迭代器指针map<int,string>::iterator
pair<map<int,string>::iterator,bool> ret = map1.insert(t1);
cout<<"insert bool="<<ret.second<<endl;
cout<<ret.first->first<<","<<ret.first->second<<endl;
cout<<(*ret.first).first<<","<<(*ret.first).second<<endl;
cout<<"after map insert"<<endl;
for(auto& elem:map1)
cout<<elem.first<<","<<elem.second<<endl;
// multimap插入
cout<<"multimap"<<endl;
multimap<int,string> mmap1(arr,arr+2);
multimap<int,string>::iterator it = mmap1.begin();
cout<<it->first<<","<<it->second<<endl;
// multimap允许关键字相同的pair存在,所以不存在插入失败的说法
// 永远返回插入元素所在multimap中的位置
it = mmap1.insert(t1);
cout<<it->first<<","<<it->second<<endl;
cout<<"after multimap insert"<<endl;
for(auto& elem:mmap1)
cout<<elem.first<<","<<elem.second<<endl;
return 0;
}
|
#include<iostream>
#include<map>
#include<string>
using namespace std;
int main()
{
pair<int,string> arr[4] =
{
pair<int,string>(1,"beijing"),
pair<int,string>(3,"shanghai"),
pair<int,string>(2,"tinjin"),
pair<int,string>(2,"shenzhen")
};
pair<int,string> x(8,"kunming");
map<int,string> map1(arr,arr+4);
map<int,string>::iterator it = map1.begin();
it++; it++; // 指针偏移
// 加快查找速度的插入
map<int,string>::iterator p = map1.insert(it,x);
cout<<"map插入后的返回值:"<<p->first<<","<<p->second<<endl;
cout<<"输出map1元素:"<<endl;
for(auto& elem:map1)
cout<<elem.first<<","<<elem.second<<endl;
cout<<"----------------------------------------------"<<endl;
multimap<int,string> mmap1(arr,arr+4);
multimap<int,string>::iterator mit = mmap1.begin();
++mit;
multimap<int,string>::iterator mp = mmap1.insert(mit,x);
cout<<"multimap插入后的返回值:"<<mp->first<<","<<mp->second<<endl;
cout<<"输出mmap1元素:"<<endl;
for(auto& elem:mmap1)
cout<<elem.first<<","<<elem.second<<endl;
cout<<endl;
return 0;
}
|
#include<iostream>
#include<map>
using namespace std;
int main()
{
pair<int,string> sz[4]={
pair<int,string>(7,"honghe"),
pair<int,string>(3,"wenshan"),
pair<int,string>(5,"baoshan"),
pair<int,string>(1,"lijiang")
};
pair<int,string> insarr[3] =
{
pair<int,string>(8,"kunming"),
pair<int,string>(6,"qujing"),
pair<int,string>(5,"dali")
};
map<int,string> map1(sz,sz+4);
map1.insert(insarr,insarr+3);
for(auto& elem:map1)
cout<<elem.first<<","<<elem.second<<endl;
multimap<int,string> mmap1(sz,sz+4);
mmap1.insert(insarr,insarr+3);
cout<<"----------------------"<<endl;
for(auto& elem:mmap1)
cout<<elem.first<<","<<elem.second<<endl;
cout<<endl;
return 0;
}
|
#include<iostream>
#include<map>
using namespace std;
template<class container>
void disp(container& m)
{
for(auto& elem:m)
cout<<elem.first<<","<<elem.second<<endl;
}
int main()
{
pair<int,string> sz[3] =
{
pair<int,string>(1,"A"),
pair<int,string>(2,"B"),
pair<int,string>(1,"C")
};
map<int,string> map1(sz,sz+3);
cout<<"map1 before erase:"<<endl;
disp(map1);
int cnt = map1.erase(1);
cout<<"map1 after erase:"<<endl;
disp(map1);
cout<<"erase "<<cnt<<" elems"<<endl;
multimap<int,string> mmap1(sz,sz+3);
cout<<"mmap1 before erase:"<<endl;
disp(mmap1);
cnt = mmap1.erase(1);
cout<<"mmap1 after erase:"<<endl;
disp(mmap1);
cout<<"erase "<<cnt<<" elems"<<endl;
return 0;
}
|