map 映照容器入门

欢迎前往我的个人博客阅读原文

类似于 python 中的字典,map 映照容器的元素数据是由一个键值和一个映照数据组成的,键值与映照数据之间具有一一映照的关系。

map 映照容器插入元素的键值不允许重复,比较函数只对元素的键值进行比较,元素的各项数据可通过键值检索出来。(map 映照容器的数据结构是采用红黑树来实现的,看来要补充的知识好多)。

使用 map 容器需要头文件包含语句:

#include<map>

map 创建、元素插入和遍历访问

创建 map 对象,键值与映照数据的类型由自己定义。在没有指定比较函数的情况下,元素的插入位置是按键值由小到大插入到红黑树中。

#include<map>
#include<string>
#include<iostream>
using namespace std;
int main(int argc, char* argv[])
{
    // 定义 map 对象,当前没有任何元素
    map<string, float> m;
    // 插入元素,按键值由小到大放入红黑树中
    m["Tsui"] = 98.5;
    m["Joshua"] = 96.0;
    m["Kristopher"] = 97.5;
    // 前向遍历元素
    map<string, float>::iterator it;
    for (it = m.begin(); it != m.end(); it++)
    {
        // 输出键值与映照数据
        cout << (*it).first << " : " << (*it).second << endl;
    }
    return 0;
}

运行结果:

alt 运行结果

容易从结果看出是按照字母顺序排列的,即按键值由小到大排列的。

删除元素

和前面学习的一样,map 映照容器删除元素也是使用 erase() 函数来实现的。它可以删除某个迭代器位置上的元素、等于某个键值的元素或者一个迭代器区间上的所有元素。当然,也和前面一样,可以使用 clear() 方法清空 map 映照容器。

#include<map>
#include<iostream>
using namespace std;
int main(int argc, char* argv[])
{
    map<int, char> m;
    m[2] = 's';
    m[3] = 'u';
    m[1] = 't';
    m[4] = 'i';
    // 删除键值为 3 的元素
    m.erase(3);
    map<int, char>::iterator it;
    for (it = m.begin(); it != m.end(); it++)
        cout << (*it).first << " : " << (*it).second << endl;
    return 0;
}

运行结果:

alt 运行结果

元素反向遍历

可以使用反向迭代器 reverse_iterator 反向遍历 map 映照容器中的数据,这里还需要使用 rbegin() 方法 rend() 方法指出反向遍历的起始位置和终止位置。

#include<map>
#include<iostream>
using namespace std;
int main(int argc, char* argv[])
{
    map<int, char> m;
    m[2] = 's';
    m[3] = 'u';
    m[1] = 't';
    m[4] = 'i';
    // 反向遍历元素
    map<int, char>::reverse_iterator rit;
    for (rit = m.rbegin(); rit != m.rend(); rit++)
        cout << (*rit).first << " : " << (*rit).second << endl;
    return 0;
}

运行结果:

alt 运行结果

元素的搜索

搜索依旧使用的是 find() 方法。使用 find() 方法搜索某个键值,如果搜索到了,则返回该键值所在的迭代器位置,否则,返回 end() 迭代器位置。例如:

#include<map>
#include<iostream>
using namespace std;
int main(int argc, char* argv[])
{
    map<int, char> m;
    m[2] = 's';
    m[3] = 'u';
    m[1] = 't';
    m[4] = 'i';
    map<int, char>::iterator it;
    // 搜索键值为 3 的元素
    it = m.find(3);
    // 搜索到该键值
    if (it != m.end())
        cout << (*it).first << " : " << (*it).second << endl;
    else
        cout << "not find it" << endl;
    return 0;
}

运行结果:

alt 运行结果

自定义比较函数

将元素插入到 map 中去时,map 会根据设定的比较函数将该元素放到该放的节点上。在定义 map 的时候,如果没有指定比较函数,那么将采用默认的比较函数,即按照键值由小到大的顺序插入元素。编写比较函数的方法有两种:

  • 如果元素不是结构体,那么,可以编写比较函数。下面这段程序编写的比较规则是按照键值由大到小的顺序将元素插入到 map 中:
#include<map>
#include<iostream>
using namespace std;

// 自定义比较函数 myComp
struct myComp
{
    bool operator()(const int &a, const int &b)
    {
        if (a != b)
            return a > b;
        else
            return a > b;
    }
};
int main(int argc, char* argv[])
{
    map<int, char, myComp> m;
    m[2] = 's';
    m[3] = 'u';
    m[1] = 't';
    m[4] = 'i';
    // 使用前向迭代器中序遍历 map
    map<int, char, myComp>::iterator it;
    for (it = m.begin(); it != m.end(); it++)
        cout << (*it).first << " : " << (*it).second << endl;
    return 0;
}

运行结果:

alt 运行结果

  • 如果元素是结构体,那么,可以直接把比较函数写在结构体内。
#include<map>
#include<string>
#include<iostream>
using namespace std;

struct Info
{
    string name;
    float score;
    // 重载 "<" 操作符,自定义排序规则
    bool operator < (const Info &a) const
    {
        // 按 score 由大到小排列。如果要由小到大排列,使用">"号即可
        return a.score < score;
    }
};

int main(int argc, char* argv[])
{
    map<Info, int> m;
    // 定义 Info 结构体变量
    Info info;
    info.name = "Joshua";
    info.score = 60;
    m[info] = 25;
    info.name = "Tsui";
    info.score = 80;
    m[info] = 10;
    info.name = "Kristopher";
    info.score = 66.5;
    m[info] = 30;
    map<Info, int>::iterator it;
    for (it = m.begin(); it != m.end(); it++)
    {
        cout << (*it).second << " : ";
        cout << ((*it).first).name << ' ' << ((*it).first).score << endl;
    }
    return 0;
}

运行结果:

alt 运行结果

map 映照容器的基本知识就到这里,另外需要注意的是,程序编译时,可能会产生代号为 “warning C4786” 的警告。“4786” 是标记符超长警告的代号。可以在程序的头文件代码前面使用 #pragma warning(disable:4786) 宏语句,强制编译器忽略该警告。4786 号警告对程序的正确性和运行并无影响。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值