C++关联容器:map,set...

本文介绍了C++中的关联容器,包括map、set、multimap和multiset。关联容器通过关键字进行元素的保存和访问,其中map是键值对,set仅包含关键字。文章详细讲解了这些容器的插入、查找、删除、遍历等基本操作,并强调了在使用map时key不应使用指针。同时提到了multimap和multiset允许重复的关键字,并介绍了它们的特点和使用。
摘要由CSDN通过智能技术生成

顺序容器是按照元素在容器中位置来保存和访问的,而关联容器则不同,它是通过关键字来进行保存和访问。C++标准库提供了8个关联容器,根据有无重复关键字,有序还是无序保存来区分:

这里写图片描述

map和set是主要的两种关联容器,map中元素为键-值,关键字起到索引作用,值为相关联数据,set只包含一个关键字。

关联容器的额外的类型别名:
 key_type: 容器的关键字类型
 mapped_type: 每个关键字关联的类型,只适用map;
 value_type: 对于set与key_type相同,对于map为pair<const key_type, mapped-type>

例:map<int ,string>::key_type v ;v为int类型
   map<int ,string>::mapped_type v ;v为string类型
   map<int ,string>::value_type v ;v为pair<const int,string>

pair类型
 在上面的代码中已经看到了pair的应用了,pair为标准库类型,在文件utility,一个pair保存两个数据,类似容器,它的实现是一个结构体,当需要将两个不同类型的值保存在一个数据类型中时pair很实用。具体初始化:

pair<int, string> s(2,"abs");    //直接赋值;
pair<int, string> s1;
pair<int, string> s2;
s1 = make_pair(3,"abs");    //函数赋值
s2.first = 1;
s2.second = "aba";       //按内部成员赋值

 
一、map

map建立了键(key)和值(value)的对应关系,key 和 value可以是任意需要的类型, 需要#include <map>。定义如:map<int, string> m;

1、插入数据

改变map中的条目非常简单,因为map类已经对[]操作符进行了重载
enumMap[1] = “One”;
enumMap[2] = “Two”;

注意map存储元素是按关键字进行排序的(从小到大),与数据添加的先后无关,还可以调用函数进行数据插入:

my_Map.insert(map<string,  int>::value_type("b",2)); 
my_Map.insert(pair<string,int>("c",3)); 

2、查找数据

map中查找数据主要有两种方式,一种通过关键字来查找,一种利用find函数。

map<int, string> m;
string ss = m[2]; //2为关键字,只有map中存在关键字2时才会成功,否则会插入一个键值为2的元素,初值为空;
m[2] += "ss"; //2关键字存在时为赋值操作,不存在时为插入操作;
m.find(key),返回对应的迭代器
//注意当获取一个map迭代器itr之后,
//itr->first为对应元素的键值,itr->second为对应元素的值

3、删除数据

移除某个map中某个条目用erase()

erase(iterator it); //通过一个迭代器对象删除
erase(iterator first, iterator last); //删除一个范围
size_type erase(const Key& key); //通过关键字删除,删除了会返回1,否则返回0
clear()就相当于 enumMap.erase(enumMap.begin(), enumMap.end());

4、遍历

map不能直接用下标进行遍历,因为用下标则表示输入的为关键字,无法遍历,一般用迭代器来实现:

map<string,int> m;
map<string,int>::iterator it;
it = m.begin();
while(it != m.end())
{
    //it->first;
    //it->second;
    it ++;         
}

5、其他函数

      begin()          返回指向map头部的迭代器
      clear()         删除所有元素
      count()          返回指定元素出现的次数
      size()           返回map中元素的个数
      swap()            交换两个map
      empty()          如果map为空则返回true
      end()            返回指向map末尾的迭代器
      get_allocator()  返回map的配置器
      max_size()       返回可以容纳的最大元素个数
      rbegin()         返回一个指向map尾部的逆向迭代器
      rend()           返回一个指向map头部的逆向迭代器

注意:C++ map中key不要使用指针,请直接使用对象。因为如果使用指针的话用函数find查找时找到的是指针,而不是指针指向的值,除非重载查找操作符

参考:C++ map的基本操作和使用
   C++中map容器的说明和使用技巧
   
二、set

set的应用和map有些类似,不过set每一个元素只有关键字,没有对应的值。set的建立:set<int> a ,set<int,greater<int>> s ,其中第二个为建立一个有大到小排序的set,(greater在头文件functional中),默认set是由小到大排序的,和map一样。

1、插入数据

set可以在定义时用数组初始化,也可以使用insert()函数来进行数据添加,set插入相同的数据时不会有效。

int a[] = {1,3,5};
set<int> s(a,a+3);   //数组初始化
set<int> d;
d.insert(3);  //insert 插入
d.insert(3);  //d中已经插入了3,不会插入

2、查找数据

set中查找数据使用find()函数,返回的是对应的迭代器。遍历set中的数据一般是使用迭代器的。

set<int> s;...
s.find(2) != s.end()   //查找到

3、删除数据

删除数据使用erase函数,主要有下面3种用法,和map是一样的

erase(iterator)     //删除定位器iterator指向的值
erase(first,second) //删除定位器first和second之间的值
erase(key_value)    //删除键值key_value的值

4、遍历

set和map一样,不支持下标访问,只能使用迭代器进行遍历访问;

set<string> sstr;
set<string>::iterator it;
it = sstr.begin();
while(it!=sstr.end()){
    cout << *it << endl;
    it++;
}

5、其他函数

begin()      //回set容器的开始迭代器
end()      //返回set容器的末尾迭代器
clear()     //删除set容器中的所有的元素
empty()     //判断set容器是否为空
max_size()   //返回set容器可能包含的元素最大个数
size()     //返回当前set容器中的元素个数

参考: STL中的set容器的一点总结

三、multimap

multimap和map类似,不过multimap可以有重复的键值。multimap的操作和map一样,都是通过insert来插入数据,不过不能像map那样支持关键字访问,查找元素也是使用find,返回第一个找到的元素迭代器。multimap还有一个函数count,用于统计相同键值的数量。只能通过迭代器访问所有元素。

#include <map>  //都在这个文件中
...
struct st{...};   //st重载了<,也可以重定义仿函数
int main()
{
    multimap<st,int> da;
    map<st,int>da2;
    st s1(2); st s2(4);
    st s3(2); st s4(1);
    da.insert(pair<st,int>(s1,1));
    da.insert(pair<st,int>(s2,2));
    da.insert(pair<st,int>(s3,3));
    da.insert(pair<st,int>(s4,4));
    da2[s1] = 1; da2[s2] = 2;  //map才能这样用关键字来访问
    da2[s3] = 3; da2[s4] = 4;  //map可以和上面一样用insert
    int i = da.count(s3);   //multimap 计算关键字和s3相同的有几个
    return 0;
}

四、multiset

multiset和set类似,但是可以有相同的关键字,当set进行insert插入时重复的不会插入,但是multiset会,其它的两者应用相同,使用count可以计算相同关键字的个数,实际上,map和set也支持count函数,只不过存在返回1,没有返回0。

#include <map>  //都在这个文件中
...
struct st{...};   //st重载了<,也可以重定义仿函数
int main()
{
    multiset<st> da1;
    set<st> da3;
    st s1(2); st s2(4);
    st s3(2); st s4(1);
    da1.insert(s1);  da1.insert(s2);
    da1.insert(s3);  da1.insert(s4);
    da3.insert(s1);  da3.insert(s2);
    da3.insert(s3);  da3.insert(s4);
    int x = da1.count(s3);
    int j = da3.count(s3);
    return 0;
}

上面的代码中都使用了自定义结构,在结构中重载了符号<;当然不管是哪种结构set,map,multiset,multimap都支持自定义仿函数,可以在创建相应的数据结构时指定对应的仿函数,这样就可以实现同样的功能了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值