大话C++:第32篇 关联容器

1 set

set 是一种关联容器,它存储了一组唯一的元素,并保证这些元素是按某种顺序排序的。set 通常是基于平衡二叉搜索树(如红黑树)实现的,这使得它在添加、删除和查找元素时都能提供对数时间复杂度的性能。

set容器主要特点:

  • 存储不重复的元素:这是set最基本的特点,它不允许存储重复的元素,所有元素都是唯一的。

  • 自动排序:set中的元素会自动按照一定的顺序进行排序。默认情况下,元素是按照从小到大的顺序排序的,但也可以自定义排序规则。

  • 快速查找:set内部使用红黑树等数据结构实现,查找元素的时间复杂度为O(log n),因此在大量数据中能够快速查找元素。

  • 动态插入和删除元素:set支持动态地插入和删除元素,使得它在需要动态维护元素集合的场景中非常有用。

std::set 成员函数及其功能:

成员函数功能描述
insert向集合中插入一个元素。如果元素已存在,则不进行任何操作。返回一个 pair,其中包含一个迭代器指向插入的元素和一个布尔值表示插入是否成功。
emplace在集合中就地构造一个元素。这是一种更高效的方式来插入元素,因为它避免了额外的复制或移动操作。返回一个指向插入元素的迭代器。
erase从集合中删除一个元素。可以通过传递一个指向要删除元素的迭代器,或者传递一个键来删除对应的元素。返回一个指向被删除元素之后的元素的迭代器。
find在集合中查找一个元素。如果找到元素,则返回一个指向该元素的迭代器;否则返回一个指向集合末尾的迭代器(即 end())。
count返回集合中特定元素的数量。对于 std::set,由于它只包含唯一的元素,因此返回值只能是 0(表示元素不存在)或 1(表示元素存在)。
clear清除集合中的所有元素,使其变为空集合。没有返回值。
size返回集合中元素的数量。返回一个表示元素数量的无符号整数。
empty检查集合是否为空。如果集合为空,则返回 true;否则返回 false。
begin返回一个指向集合中第一个元素的迭代器。如果集合为空,则返回的迭代器等于 end()。
end返回一个指向集合末尾的迭代器。这不是一个有效的元素,而是用于表示集合的“尾后”位置。

综合案例,代码示例

#include <iostream>
#include <set>

int main() 
{
    // 创建一个空的set容器
    std::set<int> mySet;

    // 插入元素
    mySet.insert(30);
    mySet.insert(10);
    mySet.insert(20);
    mySet.insert(40);
    // 重复插入,不会有影响
    mySet.insert(10); 

    // 遍历集合并打印元素
    std::cout << "集合中元素包括: ";
    for (const auto& elem : mySet) 
    {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 查找元素
    int searchKey = 20;
    auto it = mySet.find(searchKey);
    if (it != mySet.end()) 
    {
        std::cout << "Found " << searchKey << " in mySet." << std::endl;
    } 
    else
    {
        std::cout << "Did not find " << searchKey << " in mySet." << std::endl;
    }

    // 删除元素
    int elementToRemove = 30;
    size_t removedCount = mySet.erase(elementToRemove);
    if (removedCount > 0) 
    {
        std::cout << "Removed " << elementToRemove << " from mySet." << std::endl;
    } 
    else 
    {
        std::cout << "Element " << elementToRemove << " not found in mySet." << std::endl;
    }

    // 检查集合大小
    std::cout << "Size of mySet: " << mySet.size() << std::endl;

    // 检查集合是否为空
    if (mySet.empty()) 
    {
        std::cout << "mySet is empty." << std::endl;
    } 
    else 
    {
        std::cout << "mySet is not empty." << std::endl;
    }

    // 清空集合
    mySet.clear();
    std::cout << "After clearing, mySet is empty: " << (mySet.empty() ? "true" : "false") << std::endl;

    // 插入多个元素并展示插入操作的返回值
    std::pair<std::set<int>::iterator, bool> insertResult = mySet.insert(5);
    if (insertResult.second) 
    {
        std::cout << "Inserted 5 successfully. Iterator points to: " << *insertResult.first << std::endl;
    } 
    else 
    {
        std::cout << "Failed to insert 5. Element already exists." << std::endl;
    }

    // 使用emplace就地构造插入元素
    mySet.emplace(10);
    std::cout << "Emplaced 10 into mySet." << std::endl;

    // 再次遍历集合并打印元素
    std::cout << "Elements in mySet after modifications: ";
    for (const auto& elem : mySet)
    {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

2 map

std::map是C++标准库中的一个关联容器,它包含“键值对”来存储元素。其中,每个元素的键都是唯一的,并与一个值相关联。std::map内部通常基于红黑树实现,这是一种自平衡的二叉搜索树。

std::map的主要特点:

  • 键值对存储:std::map中的每个元素都由一个键值对组成,键和值之间存在一一对应的关系。键在std::map中是唯一的,不能有重复的键。

  • 有序性:std::map中的元素默认按键的升序排列。这是因为底层红黑树的性质保证了元素的有序性。

  • 动态大小:std::map是一个动态容器,可以在运行时增加或减少元素。

  • 高效的查找、插入和删除操作:由于std::map基于红黑树实现,这些操作的时间复杂度都是O(log n),其中n是std::map中元素的数量。

std::map 成员函数及其功能:

成员函数功能描述
insert向 map 中插入一个键值对。如果键已存在,则插入失败(对于 std::map,不会替换现有元素,但对于 std::multimap,会插入多个相同键的元素)。
erase根据键删除一个元素,或者删除一个迭代器指向的元素。
find根据键查找元素,如果找到则返回指向该元素的迭代器,否则返回 end 迭代器。
count返回与特定键匹配的元素数量(对于 std::map,结果只能是 0 或 1)。
begin返回指向 map 第一个元素的迭代器。
end返回指向 map 最后一个元素之后位置的迭代器。
clear移除 map 中的所有元素。
empty检查 map 是否为空,如果为空则返回 true。
size返回 map 中元素的数量。
max_size返回 map 可能包含的最大元素数量。
swap交换两个 map 的内容。
lower_bound返回一个迭代器,指向键不小于给定值的第一个元素。
upper_bound返回一个迭代器,指向键大于给定值的第一个元素。
key_comp返回用于比较键的比较对象。
value_comp返回一个比较对象,该对象可用于比较两个元素以进行排序。
emplace构造并就地插入一个元素,避免额外的复制或移动操作。
emplace_hint带有提示的构造并就地插入一个元素,可能提高插入效率。

综合案例,代码示例

#include <iostream>
#include <map>

int main()
{
    // 创建map容器对象
    std::map<int32_t, std::string> map;
    // 插入元素
    map[1] = "hello";
    map[2] = "world";
    map[3] = "你好";
    map[4] = "世界";

    // 遍历map
    for (std::map<int32_t, std::string>::iterator iter = map.begin(); iter != map.end(); ++iter)
    {
        // 迭代器中的first表示map的key,second表示map中的value
        std::cout << "key:" << iter->first << ", value:" << iter->second << std::endl;
    }

    // 查找key为3的元素
    int32_t key = 3;
    std::map<int32_t, std::string>::iterator findIter = map.find(key);

    if (findIter != map.end())
    {
        std::cout << "找到了key为3的元素" << std::endl;

        // 插入元素
        // 重复位置插入
        // 注意,map的insert插入新的key/value
		std::pair<std::map<int32_t, std::string>::iterator, bool> res;
		res = map.insert(std::make_pair(findIter->first, "您好"));
		if (res.second)
		{
			std::cout << "插入成功" << std::endl;
		}
		else 
		{
			std::cout << "插入失败" << std::endl;
		}
		
		// map中已有的key采用本方法更新value值
        map[findIter->first] = "您好";
    }
    else
    {
        std::cout << "key为3的元素没有找到" << std::endl;
    }

    // 遍历map
    for (std::map<int32_t, std::string>::iterator iter = map.begin(); iter != map.end(); ++iter)
    {
        // 迭代器中的first表示map的key,second表示map中的value
        std::cout << "key:" << iter->first << ", value:" << iter->second << std::endl;
    }

    // 元素删除
    map.erase(key);

    // 查询map大小
    std::cout << "map大小=" << map.size() << std::endl;

    // 清理map
    map.clear();


    return 0; 
}



欢迎您同步关注我们的微信公众号!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值