有序关联容器

本文详细介绍了如何使用C++ STL中的set和map数据结构,包括向set中插入int类型及自定义类型数据,并实现自定义类型的比较运算符以支持排序。同时,展示了如何向map中插入键值对,以及遍历和输出map中的元素。

头文件:
#inlucde
#include
底层数据结构:红黑树

向有序set集合中放入int类型的数据

#include <iostream>
#include <set>
#include <map>
using namespace std;
int main()
{
    set<int> set;
    for (int i = 0; i < 20; ++i)
    {
        set.insert(rand() % 20 + 1);
    }
    for (int v : set)
    {
        cout << v << " ";
    }
    cout << endl;
}

在这里插入图片描述

向有序set集合中放入用户自定义类型的数据

#include <iostream>
#include <set>
#include <map>
using namespace std;
class Student
{
public:
    Student(int id, string name) :_id(id), _name(name) {}
    bool operator<(const Student &stu)const
    {
        return   _id < stu._id;
    }
private:
    int _id;
    string _name;
    friend ostream& operator<<(ostream& out, const Student& stu);
};
ostream& operator<<(ostream& out, const Student& stu)
{
    out << "id: " << stu._id << "name: " << stu._name << endl;
    return out;
}

int main()
{
    set<Student> set;
    set.insert(Student(2020,"张嘉文"));
    set.insert(Student(2021, "李乐"));
    set.insert(Student(2022, "无言"));
    for (auto it = set.begin(); it != set.end(); ++it)
    {
        cout << *it << endl;
    }
    return 0;
}

向有序map映射表中放入数据:

class Student
{
public:
    Student(int id = 0, string name = " ") :_id(id), _name(name) {}
private:
    int _id;
    string _name;
    friend ostream& operator<<(ostream& out, const Student& stu);
};
ostream& operator<<(ostream& out, const Student& stu)
{
    out << "id: " << stu._id << " name: " << stu._name << endl;
    return out;
}

int main()
{
    map<int, Student> stumap;
    stumap.insert({ 2020, Student(2020,"张嘉文" )});
    stumap.insert({ 2000, Student(2000,"李光") });
    stumap.insert({ 2030, Student(2030,"无言") });
    for (auto it = stumap.begin(); it != stumap.end(); ++it)
    {
        //stumap.erase(it)  stumap.erase(key)
        cout << "key: " << it->first << " value: " << it->second << " ";
    }
   // cout << stumap[2020] << endl;
    cout << endl;
}

在这里插入图片描述

<think>我们被要求解释C++关联容器的定义和种类。根据引用[2]和引用[3],关联容器是C++标准库中的一类容器,它们通过关键字(key)来存储和访问元素。关联容器分为有序关联容器和无序关联容器两大类。###有序关联容器有序关联容器使用比较运算符(默认是<)来组织元素,内部通常以平衡二叉搜索树(如红黑树)实现,因此元素总是按照关键字升序排列(除非自定义比较函数)。包括: -`set`:只存储关键字,关键字不可重复- `map`:存储键值对(key-value),每个key唯一- `multiset`:关键字可重复出现的set- `multimap`:关键字可重复出现的map###无序关联容器无序关联容器(引用[2])使用哈希函数和关键字类型的==运算符来组织元素。在关键字类型的元素没有明显序关系或维护序的代价高昂时,无序容器非常有用。包括: -`unordered_set`:哈希集合,关键字不可重复-`unordered_map`:哈希映射,每个key唯一(最常用,如引用[2]中的单词计数例子) -`unordered_multiset`:关键字可重复的unordered_set-`unordered_multimap`:关键字可重复的unordered_map###关联容器的关键特性1.**关键字要求**:有序容器要求关键字类型必须定义比较运算符(或提供自定义比较函数);无序容器要求关键字类型必须支持哈希函数和==运算符。2.**元素访问**:map和unordered_map支持下标操作(通过key访问value),但注意:下标操作可能会插入新元素(如果key不存在)。可以使用`at()`成员函数(引用[4])来访问元素,如果key不存在会抛出异常。 3. **元素查找**:使用`find()`成员函数查找元素,返回迭代器;`count()`返回关键字出现的次数(引用[4])。4.**范围查找**:有序关联容器支持`lower_bound()`、`upper_bound()`和`equal_range()`(引用[4]),用于在有序序列中定位元素范围。###示例代码引用[2]中的无序映射示例:```cppvoiduse_unorderd_map(){unordered_map<string,size_t> word_count;stringword;while(cin>> word) {word_count[word]++; //计数}for(constauto &word :word_count) {cout<< "key is" <<word.first<< "value is" <<word.second<< endl;} }``` 引用[3]中的嵌套关联容器示例(map的value是vector):```cppmap<string,vector<pair<string,string>>>peo; //姓:名字和生日// ...输入数据//遍历输出```###总结关联容器提供基于关键字的快速查找(对数时间复杂度或平均常数时间复杂度)。选择有序还是无序容器取决于是否需要对元素排序以及性能要求。---§§相关问题§§1.如何为自定义类型实现有序关联容器(如set)所需的比较函数? 2.无序关联容器的哈希函数如何自定义?3.关联容器的插入操作有哪些方法?它们有什么区别? 4.如何高效地遍历关联容器?</think>### C++ 关联容器详解 #### 1. 关联容器定义 关联容器是 C++ 标准库中的一类特殊容器,**通过关键字(key)而非位置索引来存储和访问元素**。与顺序容器(如 vector/list)不同,关联容器使用**高效的数据结构(通常是红黑树或哈希表)** 组织元素,实现快速查找(平均 $O(log n)$ 或 $O(1)$ 时间复杂度)[^2][^3]。 核心特征: - 元素以键值对(key-value)形式存储 - 自动维护元素有序性(有序容器)或哈希组织(无序容器) - 提供基于关键字的快速查找、插入和删除操作 #### 2. 关联容器分类 **有序关联容器**(基于红黑树实现): | 容器类型 | 特性描述 | 头文件 | |----------------|-----------------------------|-------------| | `std::set` | 唯一关键字集合 | `<set>` | | `std::map` | 唯一键值对映射 | `<map>` | | `std::multiset`| 允许重复关键字集合 | `<set>` | | `std::multimap`| 允许重复键值对映射 | `<map>` | **无序关联容器**(基于哈希表实现): | 容器类型 | 特性描述 | 头文件 | |------------------------|-----------------------------|-----------------| | `std::unordered_set` | 唯一关键字哈希集合 | `<unordered_set>` | | `std::unordered_map` | 唯一键值对哈希映射 | `<unordered_map>` | | `std::unordered_multiset`| 允许重复关键字哈希集合 | `<unordered_set>` | | `std::unordered_multimap`| 允许重复键值对哈希映射 | `<unordered_map>` | #### 3. 关键特性对比 | 特性 | 有序容器 | 无序容器 | |----------------------|-----------------------------|-----------------------------| | **底层结构** | 红黑树 | 哈希表 | | **元素顺序** | 按关键字严格排序 | 无特定顺序 | | **查找复杂度** | $O(log n)$ | 平均 $O(1)$,最坏 $O(n)$ | | **自定义排序** | 支持比较函数(如引用[1]) | 需自定义哈希函数和相等比较 | | **典型应用** | 需要有序访问的场景 | 快速查找且无需排序的场景 | #### 4. 基本操作示例 **有序 map 使用**(引用[3]): ```cpp std::map<std::string, std::vector<std::pair<std::string, std::string>>> people; // 插入元素 people["Smith"].emplace_back("John", "1990-01-01"); people["Smith"].emplace_back("Anna", "1992-05-15"); // 遍历输出 for (const auto& family : people) { std::cout << family.first << ":\n"; for (const auto& member : family.second) { std::cout << " " << member.first << ", born: " << member.second << "\n"; } } ``` **无序 map 使用**(引用[2]): ```cpp std::unordered_map<std::string, size_t> word_count; // 计数操作 word_count["apple"]++; word_count["banana"] = 5; // 范围查找(引用[4]) auto range = word_count.equal_range("apple"); if (range.first != range.second) { std::cout << "Count: " << range.first->second << "\n"; } ``` #### 5. 选择指南 - 需要 **元素有序遍历** 或 **范围查询**(如 `lower_bound()`)→ 选择有序容器[^4] - 追求 **最高查找性能** 且不关心顺序 → 选择无序容器[^2] - 处理 **重复关键字** → 选择 `multi` 版本容器 - 仅需 **检查存在性** → 选择 `set` 而非 `map` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值