从零开始的Cpp(4)地图map和unorder_map和try-catch

1.Map

map是一个有序的键值对容器,其中的键是唯一的,不允许重复。

它基于红黑树实现,因此插入、删除和查找操作都具有较高的效率。

元素会按照键的升序排序,默认情况下,也可以自定义排序规则。

std::map提供的一些主要操作:

插入元素:

insert():插入一个键值对或一个范围的键值对到map中。

emplace():在map中构造一个键值对。

operator[]:访问指定键对应的值,若键不存在则插入默认值。

删除元素:

erase():根据键删除一个或多个元素。

clear():清空map中的所有元素。

访问元素:

at():根据键访问对应的值,若键不存在则抛出异常。

find():根据键查找对应的元素,返回迭代器。

count():根据键统计在map中出现的次数。

大小和容量:

size():返回map中键值对的个数。

empty():检查map是否为空。

遍历元素:

使用迭代器遍历map中的键值对。

用一段代码演示Map的主要功能:

#include <iostream>
#include <map>
#include <string>
int main() {
    // 创建一个map容器,键为int类型,值为string类型
    std::map<int, std::string> myMap;

    // 三种插入元素的方式
    myMap.insert({ 3, "Three" });//insert接受的是键-值对,用花括号可以插入键-值对,或者用std::make_pair 函数来创建一个键值对,然后将其作为参数传递给 insert 函数。例如:
    myMap.insert(std::make_pair(1, "One"));
    myMap[2] = "Two";
        //在你输入之后,map会自动按照键值1 2 3进行升序排列,所以最后循环打印时,先输出键值2的键值对,后输出键值为3的键值对
            // 查找元素
    std::map<int, std::string>::iterator it = myMap.find(2);//寻找键值为2的元素,如果没有,it得到的值是myMap.end()
    if (it != myMap.end()) {
        std::cout << "Found element with key 2: " << it->second;//与(*it).second等效 << std::endl;
    }
    else {
        std::cout << "Element with key 2 not found" << std::endl;
    }

    // 删除元素
    myMap.erase(1);
    //如果 myMap 中存在键为 1 的元素,则该元素将被从容器中删除;如果不存在,则不进行任何操作。
    //注意,如果 erase 函数成功删除了元素,则返回值为 1,表示删除了一个元素;如果指定的键不存在,返回值为 0,表示没有删除任何元素。


    // 遍历输出元素
    std::cout << "Map elements in ascending order: " << std::endl;
    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }
    //也可以写for (it = myMap.begin(); it != myMap.end(); it++) {std::cout << (*it).first << ": " << (*it).second << std::endl;}

    return 0;
}

count功能:

#include <iostream>
#include <map>

int main() {
    std::map<int, int> myMap;

    // 添加一些键值对到map中
    myMap[1] = 10;
    myMap[2] = 20;
    myMap[3] = 30;
    myMap[4] = 10;
    myMap[5] = 10;

    // 统计键为1的出现次数
    int count = myMap.count(1);
    std::cout << "键为1的出现次数:" << count << std::endl;

    // 统计键为10的出现次数
    count = myMap.count(10);
    std::cout << "键为10的出现次数:" << count << std::endl;

    // 统计键为6的出现次数
    count = myMap.count(6);
    std::cout << "键为6的出现次数:" << count << std::endl;

    return 0;
}

输出结果将会是:

键为1的出现次数:1

键为10的出现次数:0

键为6的出现次数:0

operator[]和at():

`operator[]`和`at()`都可以用于访问map中的元素,但它们有一些区别:

1. 行为不同:`operator[]`在访问键不存在时会自动插入一个具有默认值的键值对,而`at()`在访问不存在的键时会抛出`std::out_of_range`异常。

2. 返回值不同:`operator[]`返回键对应的值的引用,如果键不存在,则返回一个插入的默认值的引用;`at()`返回键对应的值的拷贝,并且如果键不存在,则抛出异常。

在std::map中,at()和operator[]可以用于访问元素,但它们不属于索引和随机访问。这两个方法都是通过键来访问元素,而不是通过索引或随机访问。它们基于红黑树的特性,在平均情况下具有对数时间复杂度(O(log n))。

`std::map`的访问方式和索引/随机访问之间有以下区别:

1. 数据结构:`std::map`是基于红黑树实现的关联容器,而索引/随机访问通常是针对支持连续内存存储的容器(如`std::vector`、`std::array`等)。

2. 访问方式:`std::map`通过键来访问元素,而索引/随机访问是通过元素在容器中的位置(索引)或迭代器来访问元素。

3. 时间复杂度:`std::map`的查找、插入和删除操作都具有对数时间复杂度(O(log n)),而索引/随机访问的时间复杂度通常是常量时间复杂度(O(1))。

以下是operator[]和at()的示例代码

#include <iostream>
#include <map>

int main() {
    std::map<std::string, int> myMap;

    // 使用operator[]访问键对应的值,如果键不存在则插入默认值
    myMap["apple"] = 10;
    myMap["banana"] = 20;
    myMap["orange"] = 30;

    // 访问已存在的键
    std::cout << "键为apple的值:" << myMap["apple"] << std::endl;

    // 访问不存在的键,插入默认值
    std::cout << "键为grape的值:" << myMap["grape"] << std::endl;

    // 输出map中的所有键值对
    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

输出结果将会是:

键为apple的值:10

键为grape的值:0

apple: 10

banana: 20

grape: 0

orange: 30

我们使用`operator[]`访问不存在的键`"grape"`,由于该键不存在于map中,会插入默认值0,并输出结果。在最后的循环打印中,因为使用的是值引用,而不是迭代器,所以输出不用(*it).first解引用或者it->first,而是直接使用pair.first。

#include <iostream>
#include <map>

int main() {
    std::map<std::string, int> myMap;

    // 添加一些键值对到map中
    myMap["apple"] = 10;
    myMap["banana"] = 20;
    myMap["orange"] = 30;

    // 使用at函数获取键对应的值
    int value = myMap.at("apple");
    std::cout << "键为apple的值:" << value << std::endl;

    // 尝试获取不存在的键的值
    try {
        value = myMap.at("grape");
        std::cout << "键为grape的值:" << value << std::endl;
    }
    catch (std::out_of_range) {
        std::cout << "键为grape的值不存在。" << std::endl;
    }

    return 0;
}

输出结果将会是:

键为apple的值:10

键为grape的值不存在。

2.try-catch

try-catch是一种异常处理机制,try中是可能引发异常的代码,catch后的()是可能出现的异常,{}是处理异常的方法

如果不加try-catch,上面的程序会弹出异常:

注意,这是使用at获取键值时抛出的异常。如果使用迭代器获取,不会抛出异常,而是直接返回end()。在第一个例子中,程序使用if-else解决了这个问题。

try-catch的基本用法如下:

try {
    // 可能引发异常的代码
} catch (ExceptionType1 e1) {
    // 处理ExceptionType1类型的异常
} catch (ExceptionType2 e2) {
    // 处理ExceptionType2类型的异常
} catch (...) {
    // 处理其他类型的异常
}

可以添加最后一个catch块使用省略号(...)来捕捉其他未被前面的catch块捕捉到的异常。
try-catch还可以嵌套使用,以便更细致地处理不同类型的异常。在嵌套的try-catch块中,内层catch块可以捕获并处理内层try块中发生的异常,如果内层catch块没有捕获到异常,异常将会被传递到外层的catch块。

3.unordered_map

unordered_map和map是C++中两种不同的容器类,它们在实现和使用上有一些区别。

1. 底层实现方式不同:unordered_map使用哈希表来存储键值对,而map使用红黑树来存储键值对。哈希表的插入、查找和删除操作的平均时间复杂度为O(1),而红黑树的平均时间复杂度为O(log n)。

2. 元素的顺序不同:unordered_map中的元素是无序的,插入的顺序不会影响元素的存储顺序。而map中的元素是按照键的大小进行排序的,插入的顺序会影响元素的存储顺序。

3. 查找效率不同:由于unordered_map使用哈希表实现,查找特定元素的效率比map高。在unordered_map中,使用键进行查找的平均时间复杂度为O(1),而在map中,使用键进行查找的平均时间复杂度为O(log n)。

下面用一段代码展示under_order的主要功能

#include <iostream>
#include <unordered_map>

int main() {
    // 创建一个unordered_map
    std::unordered_map<std::string, int> umap;

    // 向unordered_map中插入键值对
    umap.insert(std::make_pair("apple", 10));
    umap.insert(std::make_pair("banana", 5));
    umap.insert(std::make_pair("orange", 8));

    // 使用下标运算符访问元素
    std::cout << "The price of apple is: " << umap["apple"] << std::endl;

    // 使用迭代器遍历unordered_map
    std::cout << "All the fruits and their prices: " << std::endl;
    for (auto it = umap.begin(); it != umap.end(); ++it) {
        std::cout << it->first << ": " << it->second << std::endl;
    }

    // 查找元素
    std::string fruit = "banana";
    auto it = umap.find(fruit);
    if (it != umap.end()) {
        std::cout << "The price of " << fruit << " is: " << it->second << std::endl;
    } else {
        std::cout << fruit << " is not found in the unordered_map." << std::endl;
    }

    // 删除元素
    umap.erase("orange");

    // 判断unordered_map是否为空
    if (umap.empty()) {
        std::cout << "The unordered_map is empty." << std::endl;
    } else {
        std::cout << "The unordered_map is not empty." << std::endl;
    }

    // 获取unordered_map的大小
    std::cout << "The size of unordered_map is: " << umap.size() << std::endl;

    return 0;
}

这段代码演示了unordered_map的基本用法。首先创建一个空的unordered_map,然后使用insert函数插入键值对。可以使用下标运算符或者迭代器来访问unordered_map中的元素。使用find函数可以查找特定的元素,如果找到则返回对应的迭代器,否则返回unordered_map的end迭代器。使用erase函数可以删除指定的元素。使用empty函数判断unordered_map是否为空,使用size函数获取unordered_map的大小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值