天天看点

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

一,相关介绍

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;
    }
}
           

运行结果:

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

现在便能正常把代码跑起来了。

另外其中的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;

}
           

运行结果:

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

从结果我们可以看到,通过相应的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”

运行结果:

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

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;
}
           

运行结果:

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

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

继续阅读