前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >STL之关联式容器map(一)

STL之关联式容器map(一)

作者头像
用户9831583
发布2022-06-16 14:40:10
3650
发布2022-06-16 14:40:10
举报
文章被收录于专栏:码出名企路

关联容器:对象的位置取决于和它关联的键的值。键可以是基本类型,也可以是类类型。

map<K,T> 类模板:定义了一个保存 T 类型对象的 map,每个 T 类型的对象都有一个关联的 K 类型的键。容器内对象的位置是通过比较键决定的,唯一的要求是键必须可以用 less<K> 比或用自己指定的另一个函数对象来替代。

类模板键:

图 表示的是 map<Name,size_t> 类型的容器,其中的 Name 类可以这样定义:

代码语言:javascript
复制
   class Name
    {
    private:
        std::string firstname{}; std::string secondname{};
    public:
        Name(std::string first, std::string second) : firstname{first}, secondname{second}{};
        Name()=default;
        bool operator<(const Name& name)
        {
            return secondname < name.secondname ||((secondname == name.secondname) && (firstname < name.firstname));
        }
    };
1.初始化
代码语言:javascript
复制
std::map<std::string, size_t> people;
std::map<std::string, size_t> people{{"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32}};
//2
std::map<std::string,size_t> people{std::make_pair("Ann",25),std::make_pair("Bill", 46),std::make_pair("Jack", 32),std::make_pair("Jill", 32)};
//3
std::map<std::string, size_t> personnel {people};
std::map<std::string, size_t> personnel {std::begin(people),std::end(people)};
//用另一个容器的元素子集来创建容器
std::map<std::string,size_t> personnel {++std::begin(people),std::end(people)};
2.插入元素

必须要求:只能插入 map 中不存在的元素。

代码语言:javascript
复制
    std::map<std:: string,size_t> people {std::make_pair ("Ann",25),std::make_pair("Bill",46) , std::make_pair ("Jack",32), std::make_pair("Jill",32)};
    auto pr = std::make_pair("Fred",22); //Create a pair element and insert it
    auto ret_pr = people.insert(pr);
    std::cout << ret_pr.first->first << " "<< ret_pr.first->second<< "" << std:: boolalpha <<ret_pr.second << "\n"; // Fred 22 true

成员函数 insert() :返回一个 pair<iterator,bool> 对象。对象的成员 first 是一个迭代器,它要么指向插入元素,要么指向阻止插入的元素。如果 map 中已经保存了一个和这个键相同的对象,就会出现后面这种情况。这个对象的成员变量 second (布尔型)是返回对象,如果插入成功,返回值为 true,否则为 false。

2.1循环访问

代码语言:javascript
复制
   for (const auto& p : people)
        std::cout << std::setw(10) << std::left << p.first << " "<< p.second <<"\n";
 Ann 25
Bill 46
Fred 22
Jack 32
Jill 32

元素是以键的升序排列的,因为 map 中默认使用 less<string> 进行排序。

2.2插入相同元素

代码语言:javascript
复制
   ret_pr = people.insert(std::make_pair("Bill", 48));
    ret_pr = people.insert(std::pair<const std::string, size_t> {"Bill", 48}
    std:: cout << ret_pr.first->first <<" "<<ret_pr.first->second<< " "<<std::boolalpha<<ret_pr.second << "\n"; // Bill 46 false
代码语言:javascript
复制
insert() 返回了一个 pair 对象 ret_pr,它的成员变量 first 指向 map 中已有的和键匹配的元素,成员变量 second 为 false,表明元素没有插入成功。

键值“Bill”对应的年龄值改为 48:

代码语言:javascript
复制
    if(!ret_pr.second) // If the element is there change the age
        ret_pr.first—>second = 48;
代码语言:javascript
复制
2.3提供一个提示符来指出元素插入的位置
代码语言:javascript
复制
auto ret_pr = people.insert(std::make_pair("Jim", 48));
people.insert (ret_pr.first, std::make_pair ("Ian", 38))
代码语言:javascript
复制
insert() 的第二个参数指定的新元素会被插入到提示符的前面,并尽可能地靠近它

如果被插入的元素已经在 map 中,会导致元素插入失败

确定元素不存在时,可以只提供一个插入符;如果不那么确定,而且仍然想使用插入符,map 中的 count() 函数会返回 map 中指定键对应元素的数目,这个数目可能是 0 或 1。

代码语言:javascript
复制
if (!people.count("Ian"))
        people.insert (ret_pr.first, std::make_pair ("Ian", 38));
代码语言:javascript
复制
当 count() 函数返回 0 时,insert() 才会被调用,这说明“Ian”键不在 map 中。

2.4外部源中的一段元素插入 map

这些元素不必来自另一个 map 容器,但必须和被插入容器中的元素是同类型。

代码语言:javascript
复制
   std::map<std::string, size_t> crowd {{"May", 55}, {"Pat",66}, {"Al", 22}, {"Ben", 44}};
    auto iter = std::begin(people);
    std::advance(iter, 4);  // begin iterator+ 4
    crowd.insert(++std::begin(people),iter); // Insert 2nd, 3rd, and 4th elements from people
代码语言:javascript
复制
2.5接受初始化列表作为参数的 insert() 版本:
代码语言:javascript
复制
crowd.insert({{"Bert", 44}, {"Ellen”, 99}});
代码语言:javascript
复制
也可以单独创建一个初始化列表,然后将它作为参数传递给 insert() 函数:
代码语言:javascript
复制
std::initializer_list<std::pair<const std:: string, size_t>>init {{"Bert", 44}, {"Ellen", 99}};
crowd.insert(init);
代码语言:javascript
复制
代码语言:javascript
复制
 
#ifndef NAME_H
    #define NAME_H
    #include <ostream>                              
    #include <istream>                              
    class Name
    {
        private:
            std::string first {};
            std::string second {};
        public:
            Name(const std::string& name1, const std::string& name2) : first (name1), second (name2) {}
            Name() = default;
    
            bool operator<(const Name& name) const
            {
                return second < name.second || (second == name.second && first < name.first);
            }
            friend std::istream& operator>>(std::istream& in, Name& name);
            friend std::ostream& operator<<(std::ostream& out, const Name& name);
    };
 
    inline std::istream& operator>>(std::istream& in, Name& name)
    {
        in >> name.first >> name.second;
        return in;
    }
  
    inline std::ostream& operator<<(std::ostream& out, const Name& name)
    {
        out << name.first + " " + name.second;
        return out;
    }
    #endif
代码语言:javascript
复制
map 容器中的元素是 std::pair<const Name,size_t> 类型,可以用下面定义的别名来简化代码:
代码语言:javascript
复制
using Entry = std::pair<const Name, size_t>;
代码语言:javascript
复制
   #include <iostream>                              
    #include <iomanip>                              
    #include <string>                              
    #include <map>                                  
    #include <utility>       // For pair<> & make_pair<>()
    #include <cctype>        // For toupper()
    #include "name.h"
    using std::string;
    using Entry = std::pair<const Name, size_t>;
    using std::make_pair;
    using std::map;

    // Create a map entry from input
    Entry get_entry()
{
        std::cout << "Enter first and second names followed by the age: ";
        Name name {};
        size_t age {};
        std::cin >> name >> age;
        return make_pair(name, age);
    }

    // Output the elements in a map
    void list_entries(const map<Name, size_t>& people)
{
        for(auto& entry : people)
        {
            std::cout << std::left << std::setw(30) << entry.first
                  << std::right << std::setw(4) << entry.second << std::endl;
        }
    }

    int main()
{
        map<Name, size_t> people {{{"Ann", "Dante"}, 25}, {{"Bill", "Hook"}, 46},
                    {{"Jim", "Jams"}, 32}, {{"Mark", "Time"}, 32}};
        std::cout << "\nThe initial contents of the map is:\n";

        list_entries(people);

        char answer {'Y'};
        std::cout << "\nEnter a Name and age entry.\n";

        while(std::toupper(answer) == 'Y')
        {
            Entry entry {get_entry()};
            auto pr = people.insert(entry);

            if(!pr.second)
            { // It's there already - check whether we should update
                std::cout << "Key \"" << pr.first->first <<
                        "\" already present. Do you want to update the age (Y or N)? ";
                std::cin >> answer;
                if(std::toupper(answer) == 'Y')
                    pr.first->second = entry.second;
            }
            // Check whether there are more to be entered
            std::cout << "Do you want to enter another entry(Y or N)? ";
            std::cin >> answer;
        }
        
        std::cout << "\nThe map now contains the following entries:\n";
        list_entries(people);
    }

结果显示:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码出名企路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.初始化
  • 2.插入元素
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档