STL之map容器使用

本文详细介绍了C++ STL中map容器的基本概念、构造方式、插入、遍历、查找及删除等核心操作,并提供了多种排序方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、map是一个关联容器,属于类模版。关联的本质是元素的值和某个特定的键相关联,而不是像数组那样通过元素在数组中的位置来获取。
特点:
1、增加删除节点对迭代器的影响很小;
2、对于迭代器来说不可以更改键值,只能修改其对应的值;
3、map内部数据的组织结构为红黑树,这棵树具有对数据自动排序的功能,所以map内部所有的数据都是有序的;
4、所选键值必须支持<重载;
5、map中存储的元素为pair类型
6、使用[]可能添加新元素 如m[3];当原来不存在key为3时会创建一个元素;

二、pair类型
学习关联容器之前,必须要了解名为pair的标准库,它定义在头文件中,用来保存两个成员数据,注意它也是一个模版,当创建一个pair时,必须提供创建两个类型名,pair的数据成员将具有对应的类型。两个类型不要求一致;
这里我们可以跳进pair源码查看pair的定义;

#include <iostream>
#include <utility>
int main()
{
    std::pair<int, string> a;//此时调用pair的默认构造函数对数据成员进行值初始化;这里的值初始化指的是内置类型元素初始化为0,如int初始化为0;类类型元素调用默认构造函数
    cout<<a.first<<endl; 
    cout<<a.second<<endl;

}

三、构造方式:
使用时注意导入头文件

#include <iostream>
#include <map>
int main(int argc ,char* argv[])
{
    map<int,string> mapTest1;//构造一个空的map容器
    map<int,string> mapTest2{{1,"zhao"},{2,"qian"}};//使用列表初始化map容器
    map<int,string> mapTest3{pair<int,string>(1,"zhao")};//使用pair初始化;
    map<int,string> mapTest4(mapTest3.begin(),mapTest4.end());//使用迭代器初始化;
    map<int,string> mapTest5(mapTest2);//使用已有对象初始化map容器 
}

四、插入操作
1、使用函数insert(),同一个key有数据之后insert将失败;
2、使用数组方式插入,则会直接覆盖掉原来的值;

int main(int argc, const char * argv[])
{

    map<int,string> mapTest{pair<int, string>(1,"gg"),{2,"tt"}};
    mapTest.insert({2,"heh"});//插入失败,不报错,只是插入不成功
    mapTest[1] = "xx";//覆盖掉原来的键(key)'1'对应的值(value)“gg”;
    for(auto v:mapTest)
    {
        cout<<v.first;
        cout<<v.second<<endl;
    }
    return 0;
}

五、遍历操作
1、第一种使用范围for循环

int main(int argc, const char * argv[])
{
    map<int,string> mapTest{{1,"gg"},{2,"tt"}};
    for(auto v:mapTest) //注意此时的v为pair类型
    {
        cout<<v.first;
        cout<<v.second<<endl;
    }
    return 0;
}

2、第二种使用迭代器的方式

int main(int argc, const char * argv[])
{
    map<int,string> mapTest{{1,"gg"},{3,"tt"}};
    map<int,string>::iterator itor = mapTest.begin();
    while (itor != mapTest.end())
    {
        cout<<itor->first<<endl;
        cout<<itor->second<<endl;
        ++itor;
    }
    return 0;
}

3、如果容器的key值为int,使用下标遍历会出现什么问题?

int main(int argc, const char * argv[])
{
    map<int,string> mapTest{{1,"gg"},{3,"tt"}};
    for(int i = 1;i <= mapTest.size();++i)
    {
        cout<<mapTest[i]<<endl;
    }
    return 0;
    //输出的结果有什么问题呢?
}

六、查找操作
1、第一种使用count函数来判断关键字是否出现,缺点是无法确定出现的位置,由于map的一对一映射特点,决定了count函数的返回值只有两个,要么为0,要么为1,当为0时表示不存在,为1时存在

int main(int argc, const char * argv[])
{
    map<int,string> mapTest{{1,"gg"},{3,"tt"}};
    if(mapTest.count(2) == 0)
    {
        cout<<"key为2的元素不存在"<<endl;
    }else
    {
        cout<<"key为2的元素存在"<<endl;
    }
    return 0;
}

2、使用find()函数定位数据出现的位置,当key值存在时,返回对应位置的迭代器,否则返回end()函数返回的迭代器;

int main(int argc, const char * argv[])
{
    map<int,string> mapTest{{1,"gg"},{3,"tt"}};
    auto p = mapTest.find(1);
    if(p != mapTest.end())
    {
        cout<<p->first<<endl;
        cout<<p->second<<endl;
    }else
    {
        cout<<"key为1的元素不存在"<<endl;
    }
    return 0;
}

七、删除操作
1、通过key值来删除元素

int main(int argc, const char * argv[])
{
    map<int,string> mapTest{{1,"gg"},{3,"tt"}};
    mapTest.erase(1);
    for (auto v : mapTest)
    {
        cout<<v.first<<endl;
        cout<<v.second<<endl;
    }
    return 0;
}

2、通过迭代器删除

int main(int argc, const char * argv[])
{
    map<int,string> mapTest{{1,"gg"},{3,"tt"}};
    mapTest.erase(mapTest.begin());//删除指定位置
    mapTest.erase(mapTest.begin(),--mapTest.end());//删除指定范围
    for (auto v : mapTest)
    {
        cout<<v.first<<endl;
        cout<<v.second<<endl;
    }
    return 0;
}

八、排序操作
学习map排序之前我们要注意,map容器默认将元素按照key值由小到大排序;
1、使用库函数实现按照key从大到小排序

int main(int argc, const char * argv[])
{
    map<int,string,greater<int>> mapTest{{1,"gg"},{3,"tt"},{4,"aa"}};
    for (auto v: mapTest)
    {
        cout<<v.first<<endl;
    }
    return 0;
}

2、自定义实现按照key从小到大排序

struct ComByKey
{
    bool operator()(const int& k1,const int& k2)const
    {
        return k1 > k2;
    }
};
int main(int argc, const char * argv[])
{
    map<int,string,ComByKey> mapTest{{1,"gg"},{3,"tt"},{4,"aa"}};
    for (auto v: mapTest)
    {
        cout<<v.first<<endl;
    }
    return 0;
}

3、自定义实现map中的value从小到大排序
主要思路讲map中的元素转存到vector中,在对vector进行排序

typedef pair<int, string> MyPair;
bool comByVal(const MyPair& v1,const MyPair& v2)//定义vector容器的比较规则
{
    return v1.second < v2.second;
}
int main(int argc, const char * argv[])
{
    map<int,string> mapTest{{1,"gg"},{3,"tt"},{4,"aa"}};
    vector<MyPair> V(mapTest.begin(),mapTest.end());
    sort(V.begin(), V.end(), comByVal);
    for (auto v: V)
    {
        cout<<v.second<<endl;
    }
    return 0;
}

九、其他操作
begin() 返回指向map头部的迭代器
end() 返回指向map末尾元素的下一个的迭代器
rbegin() 返回一个指向map尾部的逆向迭代器
rend() 返回一个指向map头部前一个元素的逆向迭代器

size() 返回map中元素的个数
empty() 如果map为空则返回true
clear() 删除所有元素
swap() 交换两个map
lower_bound() 返回键值>=给定key值的第一个元素的迭代器
upper_bound() 返回键值>给定key值的第一个元素的迭代器

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值