当前位置: 代码迷 >> 综合 >> c++ map/multimap,set/multiset的用法及比较
  详细解决方案

c++ map/multimap,set/multiset的用法及比较

热度:7   发布时间:2023-12-16 16:14:44.0

一,相关介绍
map/multimap,set/multiset都为c++中的标准容器,它们的底层都是用红黑树实现的,因此在进行查询,修改,删除等操作上具有很高的效率,可以达到O(logN)。
那么它们的区别是什么呢?
1,其中map/multimap是kay-value结构,意思为它存储的是一对数据,其中kay为关键字信息,而value为相应的键值;而set/multiset为kay结构,它没有相应的value信息。
2,由于map/set是用红黑树实现的,所以它不允许kay值相同的数据插入(在后面的例子中我们将展现这种特性);为了应对相应的需求,于是便有了multimap和multiset,它们允许kay值相同的数据插入。
二,具体使用
注意:在使用前需要包相应的头文件。
1,map的使用

#pragma once
#include<map>
#include<set>
#include<string>
#include<iostream>
using namespace std;
//map与set都是c++里面的标准容器,它们底层的实现都是通过红黑树完成的,而map与set的区别在与map为kay-value结构,而set为key结构
//由于是红黑树,所以它里面不允许有相同kay值存在,所以若重复插入,结果不变。
void myTest()
{map<string, string> myMap;myMap.insert("left", "左边");myMap.insert("right", "右边");map<string, string>::iterator it = myMap.begin();for (; it != myMap.end(); it++){cout << (*it)<<endl;}
}

上面为自定义的一个map(为string-string类型),然后向里面插入了两个值(map为kay-value结构);
紧接着我们又定义了一个迭代器it,其中begin()方法是用来获取map中的第一个数据,end( )则用来获得最后一个数据。
细心的朋友会发现,这份代码并不能跑起来(直接编译不通过),并且提示insert那里有问题,其实这是因为,在STL中,为了方便迭代器的实现(感兴趣的同学可以去查看相应的资料),在map中的insert并不是直接插入数据的,它插入的是一个pair的对象;pair是一个结构体,它如下结构

template<class k,class v>
struct pair{k _first;v _second}

在c++里面已经定义好了该结构,它的make_pair(k,v)方法便是用来生成pair类型的变量的,搞清楚了这个问题,我们再修改代码

#pragma once
#include<map>
#include<set>
#include<string>
#include<iostream>
using namespace std;
//map与set都是c++里面的标准容器,它们底层的实现都是通过红黑树完成的,而map与set的区别在与map为kay-value结构,而set为key结构
//由于是红黑树,所以它里面不允许有相同kay值存在,所以若重复插入,结果不变。
void myTest()
{map<string, string> myMap;myMap.insert(make_pair("right", "右边"));myMap.insert(make_pair("hello", "你好"));myMap.insert(make_pair("where", "哪里"));//myMap["1112"] = "无语de today";map<string, string>::iterator it = myMap.begin();for (; it != myMap.end(); it++){cout << (*it).first<<" "<<(*it).second<<endl;}
}

运行结果:
这里写图片描述
现在便能正常把代码跑起来了。
另外其中的it是迭代器,begin()方法用来返回map中的第一个数据,而end方法用来返回map中最后一个数据,此处我们用来遍历myMap;正如前面所讲的一样,由于map中插入的是一个pair对象,而*it便是pair对象,所以我们可以调用它的first及second方法间接的完成对kay-value的访问
那么数据该怎么删除呢?
(1)
iterator erase (const_iterator position);
(2)
size_type erase (const key_type& k);
(3)
iterator erase (const_iterator first, const_iterator last);
以上是map提供的对数据的删除方法,我们可以看到可以通过erase删除一个迭代器所指向的节点
也可以删除指定的k,甚至可以删除一个迭代器区间,此处便不再演示。
对数据的查找:find()方法
首先先看函数的原型:
iterator find (const key_type& k);
const_iterator find (const key_type& k) const;
它的返回值是iterator,即一个迭代器;其中const_iterator返回的为const迭代器,它所指向的pair所指向的值是不可以被修改的;接下来我们来测试一下普通迭代器的find()方法:

#pragma once
#include<map>
#include<string>
#include<iostream>
using namespace std;
//map与set都是c++里面的标准容器,它们底层的实现都是通过红黑树完成的,而map与set的区别在与map为kay-value结构,而set为key结构
//由于是红黑树,所以它里面不允许有相同kay值存在,所以若重复插入,结果不变。
void myTest()
{map<string, string> myMap;myMap.insert(make_pair("right", "右边"));myMap.insert(make_pair("hello", "你好"));myMap.insert(make_pair("where", "哪里"));cout << myMap.find("right")->second << endl;cout << myMap.find("hello")->second << endl;cout << myMap.find("where")->second << endl;}

运行结果:
这里写图片描述
从结果我们可以看到,通过相应的key值便能找到对应的value,但是需要注意的是如果查找一个不存在的将会产生一个中断,另外若想通过value查找key也会出错。为了避免没有查到相应的key
值而出错,我们可以选择一个迭代器指向自定义map的最后,如果通过find()返回的迭代器与其end相同就代表没有找到,并输出相应的信息。修改后的主要代码如下:

map<string, string>::iterator it;map<string, string>::iterator flag=myMap.end();it = myMap.find("wuyu");if (it != flag){cout << (*it).second << endl;}else{cout << "没有找到" << endl;}

此时查找key值为:“wuyu”
运行结果:
这里写图片描述

map数据的修改
请看代码:
方式1:

map<string, string> myMap;myMap.insert(make_pair("right", "右边"));myMap.insert(make_pair("hello", "你好"));myMap.insert(make_pair("where", "哪里"));myMap.insert(make_pair("left", "左边"));map<string, string>::iterator it;map<string, string>::iterator flag=myMap.end();it = myMap.find("left");if (it != flag){(*it).second = "剩余";}else{cout << "没有找到" << endl;}for (it = myMap.begin(); it != myMap.end(); it++){cout << (*it).first << " " << (*it).second << endl;}cout << endl;

方式2:

#pragma once
#include<map>
#include<string>
#include<iostream>
using namespace std;
//map与set都是c++里面的标准容器,它们底层的实现都是通过红黑树完成的,而map与set的区别在与map为kay-value结构,而set为key结构
//由于是红黑树,所以它里面不允许有相同kay值存在,所以若重复插入,结果不变。
void myTest()
{map<string, string> myMap;myMap.insert(make_pair("right", "右边"));myMap.insert(make_pair("hello", "你好"));myMap.insert(make_pair("where", "哪里"));myMap.insert(make_pair("left", "左边"));map<string, string>::iterator it;map<string, string>::iterator flag=myMap.end();it = myMap.find("left");if (it != flag){(*it).second = "剩余";}else{cout << "没有找到" << endl;}for (it = myMap.begin(); it != myMap.end(); it++){cout << (*it).first << " " << (*it).second << endl;}cout << endl;//通过[]实现myMap["where"] = "在哪里";myMap["left"] = "左边";for (it = myMap.begin(); it != myMap.end(); it++){cout << (*it).first << " " << (*it).second << endl;}cout << endl;
}

运行结果:
这里写图片描述
我们可以使用find()方法先找到指定的节点,再对其指向的key->value直接进行修改,但这种方法较为麻烦;我们比较常用的是直接调“【】”运算符,由于在定义iterator时对它进行了重载,所以可以直接访问相应的数据并对其进行修改。