C++编程语言STL之map及相关容器介绍

本文主要介绍C++编程语言的STL(Standard Template Library)中map及相关容器的相关知识,同时通过示例代码介绍这些容器的使用方法。

1 概述

关联容器(associative-container)和顺序容器有着根本的不同:关联容器中的元素是按关键字来保存和访问的,而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的。

虽然关联容器的很多行为与顺序容器相同,但其不同之处反映了关键字的作用。关联容器支持高效的关键字查找和访问。

两个主要的关联容器类型为mapset。map中的元素是一些关键字-值(key-value)对:“关键字”起索引的作用,“值”则表示与索引相关联的数据。set中每个元素只包含一个关键字。

2 map

2.1 特性

map的特性如下:

  • 每个关键字只能出现一次;
  • 默认按key的升序存储元素;
  • 使用红黑树(red-black trees)作为底层数据结构。

2.2 常见用法

2.2.1 构造map

构造map的方法如下(以键值对为“int-string”类型为例):

map<int, string> mapStudent;

2.2.2 插入元素

map提供了若干种插入元素的方法。

使用insert函数插入pair数据:

mapStudent.insert(pair<int, string>(1, "zhao"));
mapStudent.insert(pair<int, string>(2, "qian"));
mapStudent.insert(pair<int, string>(3, "sun"));

使用数组方式插入数据:

mapStudent[1] = "zhao";
mapStudent[2] = "qian";
mapStudent[3] = "sun";

说明:上面的两种方法是有区别的,用insert函数插入数据,涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是不能实现数据插入的;但是数组方式能够插入数据,插入的数据会覆盖该关键字之前对应的值。

2.2.3 遍历数据

可以通过map的迭代器iterator、调用map对象的begin()和end()函数,实现对于map中数据的遍历操作,示例代码如下:

// 遍历
cout << "content of map as followed: " << endl;
mapStudent_t::iterator iter;
for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
{
    cout << iter->first << " " << iter->second << endl;
}

说明:

1)begin()和end()两个成员函数,分别对应map对象中第一个数据条目和最后一个数据条目,这两个数据条目的类型是iterator;

2)通过map对象的方法获取到的iterator数据类型是一个std::pair对象,iterator数据类型包括下面两个数据:

  • iterator->first:关键字(key)
  • iterator->second:存储的数据(value)

2.2.4 查找元素

可以通过使用map的迭代器iterator、调用find函数(传入的参数为要查找的key),来查找具体的元素,示例代码如下:

// 查找
iter = mapStudent.find(2);
if (iter != mapStudent.end())
{
    cout << "Find it, the relative value is: " << iter->second << endl;
}
else
{
    cout << "Can not find the relative value." << endl;
}

说明:find函数的入参为map的key,并且入参必须完全匹配map的key,才能找到对应元素的value。例如,对于以下map结构:

mapStudent.insert(pair<string, string>("zhao", "zhaoyun"));

如果要查找该map中的元素,必须在find函数中输入完整的key(即“zhao”)才行,如果输入的入参为“zh”、或“zha”,都不能找到该元素。

2.2.5 删除数据

对于map中的数据删除操作,分为以下两种情况:

1)如果想要清空map中的所有数据,可以使用clear函数;

2)如果想要删除map中的指定数据,可以通过使用map的迭代器iterator、调用erase函数来实现,示例代码如下:

// 删除
iter = mapStudent.find(3);
mapStudent.erase(iter);

2.3 示例程序

2.3.1 示例程序1

此处展示一个输出map结构内容的示例代码。代码(map_test1.cpp)内容如下:

#include <iostream>
#include <map>

using namespace std;

int main()
{
    // <int, string>结构的map
    typedef std::map<int, string> mapStudent_t;
    mapStudent_t mapStudent;

    mapStudent.insert(pair<int, string>(1, "zhao"));
    mapStudent.insert(pair<int, string>(2, "qian"));
    mapStudent.insert(pair<int, string>(3, "sun"));

    // map简单的输出方法
    cout << "mapStudent[1] is: " << mapStudent[1] << endl;
    cout << "mapStudent[3] is: " << mapStudent[3] << endl;

    // <string, string>结构的map
    typedef std::map<string, string> mapRole_t;
    mapRole_t mapRole;

    mapRole.insert(pair<string, string>("mage", "alliance"));
    mapRole.insert(pair<string, string>("paladin", "alliance"));
    mapRole.insert(pair<string, string>("warlock", "Horde"));

    // map简单的输出方法
    cout << "mapRole[\"mage\"] is: " << mapRole["mage"] << endl;
    cout << "mapRole[\"warlock\"] is: " << mapRole["warlock"] << endl;

    return 0;
}

编译并执行上述代码,结果如下:

2.3.2 示例程序2

示例代码(map_test2.cpp)内容如下:

#include <iostream>
#include <map>
#include <string>

using namespace std;

int main()
{
    typedef std::map<int, string> mapStudent_t;
    mapStudent_t mapStudent;

    mapStudent.insert(pair<int, string>(1, "zhao"));
    mapStudent.insert(pair<int, string>(2, "qian"));
    mapStudent.insert(pair<int, string>(3, "sun"));

    // 遍历
    cout << "content of map as followed: " << endl;
    mapStudent_t::iterator iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << " " << iter->second << endl;
    }

    // 查找
    iter = mapStudent.find(2);
    if (iter != mapStudent.end())
    {
        cout << "Find it, the relative value is: " << iter->second << endl;
    }
    else
    {
        cout << "Can not find the relative value." << endl;
    }

    // 删除
    iter = mapStudent.find(3);
    mapStudent.erase(iter);

    // 再次遍历,观察删除操作是否成功
    cout << "after delete, content of map as followed: " << endl;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << " " << iter->second << endl;
    }
    
    return 0;
}

上述代码运行结果如下:

3 unordered_map

C++标准库提供了四个无序关联容器(unordered associated container),这些容器不是使用比较运算符、而是使用一个哈希函数(hash function)和关键字类型的==运算符来组织元素。

在关键字类型的元素没有明显的“序关系”的情况下,无序容器是非常有用的。在某些应用中,维护元素的序的代价非常高昂,此时无序容器也很有用。

unordered_map 就是 C++标准库提供的四个无序关联容器之一。

3.1 特性

unordered_map的特性如下:

  • 每个关键字(key)只能出现一次;
  • 根据key的哈希值将元素存储在指定位置,因此存储的元素是无序的;
  • 使用哈希表(Hash Table)作为底层数据结构。

3.2 常见用法

3.2.1 构造unordered_map

构造unordered_map的方法如下(以key和value均为char类型为例):

unordered_map<char, char> unoMap;

3.2.2 插入元素

可以通过[]运算符来执行插入元素操作,示例代码如下:

unoMap['a'] = 'b';

说明:如果key对应的value存在,则执行更新元素操作,否则执行添加元素操作。

3.2.3 查找元素

可以通过使用unordered_map的迭代器iterator、调用find函数(传入的参数为要查找的key),来查找具体的元素,示例代码如下:

// 查找
if (mapStudent.find(2) != mapStudent.end())
{
    ...
}

此外,也可以通过[]运算符来执行查找元素操作,示例代码如下:

char chValue = unoMap['a'];

3.2.4 计算字符串中各个字符出现的次数

利用unordered_map计算字符串中各个字符出现的次数,示例代码如下:

string strDemo = "aabcccc";
unordered_map<char, int> unoMap;
for (auto ch:strDemo) {
    // unoMap[ch] 即为 ch 字符对应的出现次数
    unoMap[ch]++;
}

3.2.5 查看元素出现的次数

查询某元素在unordered_map中出现的次数,方法如下(返回0或1):

m.count(i)

4 关于有序与无序

STL默认提供的map是“有序”的(即“map”),同时也提供了对应的“无序”版本(即“unordered_map”)。

对于map容器来说,存储于其中的元素是否有序,只会在使用迭代器iterator等场景下对我们有影响,而当我们使用key-value获取元素内容时,无论使用有序或无序容器,都可以得到正确的结果。

下面给出一个简单的示例代码:

#include <map>
#include <unordered_map>
#include <iostream>

using namespace std;

int main()
{
    map<int, char> Map;
    Map[1] = 'a';
    Map[2] = 'b';
    Map[3] = 'c';
    Map[4] = 'd';
    Map[5] = 'e';

    cout << "the Map output is: " << endl;
    for (auto i = Map.begin(); i != Map.end(); i++) {
        std::cout << i->first << ' ' << i->second << std::endl;
    }   
    cout << "Map[2] is: " << Map[2] << endl;

    unordered_map<int, char> unoMap;
    unoMap[1] = 'a';
    unoMap[2] = 'b';
    unoMap[3] = 'c';
    unoMap[4] = 'd';
    unoMap[5] = 'e';
        
    cout << "the unordered_map output is: " << endl;
    for (auto i = unoMap.begin(); i != unoMap.end(); i++) {
        std::cout << i->first << ' ' << i->second << std::endl;
    }   
    cout << "unoMap[2] is: " << unoMap[2] << endl;

    return 0;
}

上方代码的输出结果如下:

从上述代码运行结果可以看出:

  • 当使用迭代器iterator访问map容器中元素时,map与unordered_map结果不同,其中map是有序的,而unordered_map是无序的(似乎是倒序,待确认);
  • 使用下标法获取元素值时,无论map容器中元素是否有序,都可以获取到正确的结果。

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 在网络编程中,C++STL(Standard Template Library)是一个非常有用的工具。STL提供了许多数据结构和算法,可以帮助我们更轻松地处理网络编程中的各种任务。 首先,STL容器类是网络编程中经常用到的数据结构。例如,我们可以使用STL的vector来存储动态大小的数组,非常适用于存储和处理网络数据。此外,STLmap和unordered_map类可以用于构建键值对结构,方便快速地查找和操作网络数据。 STL还提供了一系列的算法,可以用于处理网络编程中的常见任务。例如,我们可以使用STL的sort算法对网络数据进行排序,使用STL的find算法查找某个特定的数据,或者使用STL的accumulate算法计算网络数据的总和。这些算法能够在网络编程中提高代码的效率和可读性。 此外,STL还提供了一些其他功能,如字符串处理和输入输出操作等,这些功能在网络编程中也非常有用。 总之,C++STL在网络编程中是一个强大且方便的工具。它提供了多种数据结构和算法,可以帮助我们更轻松地处理网络数据,并提高代码的效率和可读性。无论是处理数据、查找特定的值还是进行计算,STL都能够提供相应的功能,使网络编程变得更加简单和高效。 ### 回答2: C++ STL(标准模板库)是C++语言的一个重要部分,它提供了一系列的模板类和函数,用于实现常用的数据结构和算法。网络编程是指利用计算机网络进行数据传输和通信的一种编程方式。 在C++中使用STL进行网络编程时,可以使用STL提供的一些容器类和算法来简化网络编程的过程。例如,使用vector可以方便地管理接收或发送的数据;使用algorithm库中的函数可以快速处理数据;使用string类可以方便地操作字符串等。 对于网络编程,C++ STL没有直接提供相应的网络编程接口,而是需要借助于操作系统提供的网络编程库(如Socket套接字编程)来实现网络通信。通过将底层的网络库和STL进行结合,可以更加方便和高效地编写网络应用程序。 在网络编程中,可以使用STL中的容器类来存储和管理从网络中接收到的数据,例如使用vector来存储接收到的数据包,或者使用list来保存已连接的客户端。同时,可以使用STL中的算法来处理这些数据,例如使用find函数查找数据包中的特定元素。 除此之外,STL还提供了一些有用的函数和类,例如thread类可以用于多线程编程,用于处理并发的网络请求;atomic类可以保证对共享数据的原子性操作,用于实现线程安全的网络通信。 总而言之,C++ STLC++编程中的重要工具,它提供了一系列的模板类和函数,可以方便地实现网络编程中的数据管理和算法处理,而网络编程则是利用计算机网络进行数据传输和通信的一种编程方式。 ### 回答3: C++ STL(Standard Template Library)是一组标准库,提供了许多常用的数据结构和算法。它包含的容器类(如vector、list、map等)可以方便地存储和操作数据,而提供的算法则可以实现一些常用的数据处理操作(如排序、查找等)。 在网络编程方面,C++ STL可以使用socket库(socket.h)来实现网络通信。通过socket库,可以创建网络套接字(socket),并使用套接字进行数据的收发。 C++ STL中的vector可以被用来存储接收和发送的数据,可以使用其成员函数push_back()向vector中添加数据,使用operator[]访问vector中的数据。使用vector的好处是可以动态调整容器大小,使得数据存储更加方便。 通过网络套接字的recv()函数可以接收网络中传来的数据,而send()函数可以将数据发送到网络中。需要注意的是,在使用recv()函数接收数据时,应该使用一个循环来确保接收到完整的数据。可以使用std::string和字符数组来存储接收和发送的数据。 除了基本的网络通信,C++ STL还提供了一些辅助函数,用于解析和构造网络地址。例如,使用inet_ntoa()函数可以将IP地址从网络字节顺序转换为字符串形式,而inet_aton()函数则可以将IP地址从字符串形式转换为网络字节顺序。 总而言之,C++ STL可以在网络编程中提供丰富的数据结构和算法,使开发者可以更加轻松地实现各种网络应用。使用网络套接字和STL提供的功能,可以实现数据的发送和接收,并对数据进行各种处理和操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liitdar

赠人玫瑰,手有余香,君与吾共勉

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值