学懂C++(四十五 ):深入详解C++ STL 容器:从基础到进阶

      

目录

1. 向量(Vector)

概念

特点

核心点

实现

适用场景

代码解析

2. 双端队列(Deque)

概念

特点

核心点

实现

适用场景

代码解析

3. 列表(List)

概念

特点

核心点

实现

适用场景

代码解析

4. 集合(Set)

概念

特点

核心点

实现

适用场景

代码解析

5. 映射(Map)

概念

特点

核心点

实现

适用场景

代码解析

6. 无序集合(Unordered Set)

概念

特点

核心点

实现

适用场景

代码解析

7. 无序映射(Unordered Map)

概念

特点

核心点

实现

适用场景

代码解析

8. 栈(Stack)

概念

特点

核心点

实现

适用场景

代码解析

9. 队列(Queue)

概念

特点

核心点

实现

适用场景

代码解析

10. 优先队列(Priority Queue)

概念

特点

核心点

实现

适用场景

代码解析

总结


          C++ 标准模板库(STL)是一个非常强大的工具集,提供了一组通用的类和函数,用于数据结构和算法的实现。STL 的核心组件包括容器(Containers)、迭代器(Iterators)和算法(Algorithms)。本文将深入探讨 STL 容器,全面讲解其概念、特点、核心点、实现、适用场景,并通过经典示例代码和详细解析,帮助开发者更好地理解和应用 STL 容器。

1. 向量(Vector)

概念

std::vector 是一个模板类,表示一个可以动态调整大小的数组。它可以高效地在末尾添加和删除元素,提供随机访问功能。

特点

  • 动态大小:可以自动调整大小。
  • 随机访问:支持常数时间的随机访问。
  • 连续内存:存储在连续的内存块中,兼容C风格数组。

核心点

  • 内存管理:使用动态数组管理内存,自动处理内存分配和释放。
  • 扩展策略:当容量不足时,通常会按一定比例(通常是2倍)扩展容量。

实现

#include <iostream>
#include <vector>

void vectorExample()
{
    std::vector<int> vec;

    // 添加元素
    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);

    // 随机访问
    std::cout << "Element at index 1: " << vec[1] << std::endl;

    // 迭代访问
    for(const auto& elem : vec)
    {
        std::cout << elem << " ";
    }
    std::cout << std::endl;
}

适用场景

  • 需要动态调整大小的数组。
  • 需要高效随机访问的场景。

代码解析

  1. push_back:在向量末尾添加元素。
  2. 随机访问:使用下标操作符[]访问元素。
  3. 迭代访问:使用范围基于(range-based)for循环迭代访问元素。

2. 双端队列(Deque)

概念

std::deque 是一个双端队列,支持在两端高效地添加和删除元素。

特点

  • 双端操作:在两端添加和删除元素都很高效。
  • 随机访问:支持常数时间的随机访问。
  • 分段存储:内部实现为一组连续的内存块,提高内存管理效率。

核心点

  • 双端操作push_front 和 push_back 方法用于在两端添加元素。
  • 内存管理:使用分段存储来优化内存管理。

实现

#include <iostream>
#include <deque>

void dequeExample()
{
    std::deque<int> deq;

    // 在两端添加元素
    deq.push_back(1);
    deq.push_back(2);
    deq.push_front(0);

    // 随机访问
    std::cout << "Element at index 1: " << deq[1] << std::endl;

    // 迭代访问
    for(const auto& elem : deq)
    {
        std::cout << elem << " ";
    }
    std::cout << std::endl;
}

适用场景

  • 需要在两端频繁添加和删除元素的场景。
  • 需要高效随机访问的场景。

代码解析

  1. push_front:在队列前端添加元素。
  2. push_back:在队列末尾添加元素。
  3. 随机访问:使用下标操作符[]访问元素。

3. 列表(List)

概念

std::list 是一个双向链表,支持在任意位置高效地插入和删除元素。

特点

  • 双向链表:每个元素包含指向前后元素的指针。
  • 高效插入和删除:在链表的任意位置插入和删除元素都很高效。
  • 顺序访问:不支持随机访问,只能顺序访问。

核心点

  • 链表结构:使用双向链表实现,保证高效的插入和删除操作。
  • 迭代器:提供双向迭代器,支持前向和后向遍历。

实现

#include <iostream>
#include <list>

void listExample()
{
    std::list<int> lst;

    // 添加元素
    lst.push_back(1);
    lst.push_back(2);
    lst.push_front(0);

    // 迭代访问
    for(const auto& elem : lst)
    {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 插入和删除元素
    auto it = lst.begin();
    ++it;
    lst.insert(it, 10);
    lst.erase(it);
}

适用场景

  • 需要在任意位置频繁插入和删除元素的场景。
  • 需要顺序访问的场景。

代码解析

  1. push_front:在链表前端添加元素。
  2. push_back:在链表末尾添加元素。
  3. inserterase:在链表的任意位置插入和删除元素。
  4. 迭代访问:使用范围基于(range-based)for循环迭代访问元素。

4. 集合(Set)

概念

std::set 是一个有序集合,存储唯一的元素并自动对元素进行排序。

特点

  • 有序:元素自动排序。
  • 唯一性:集合中的元素是唯一的。
  • 高效查找:支持对元素的高效查找。

核心点

  • 有序集合:使用红黑树实现,保证元素的有序性和查找效率。
  • 唯一性:自动去重,保证元素的唯一性。

实现

#include <iostream>
#include <set>

void setExample()
{
    std::set<int> s;

    // 添加元素
    s.insert(3);
    s.insert(1);
    s.insert(2);
    s.insert(2); // 重复元素插入无效

    // 迭代访问
    for(const auto& elem : s)
    {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 查找元素
    auto it = s.find(2);
    if(it != s.end())
    {
        std::cout << "Element found: " << *it << std::endl;
    }
    else
    {
        std::cout << "Element not found" << std::endl;
    }
}

适用场景

  • 需要存储唯一且有序的元素集合。
  • 需要高效查找元素的场景。

代码解析

  1. insert:在集合中添加元素,自动去重。
  2. find:在集合中查找元素。
  3. 迭代访问:使用范围基于(range-based)for循环迭代访问元素。

5. 映射(Map)

概念

std::map 是一个有序映射,存储键值对,并根据键对元素进行排序。

特点

  • 有序:键值对自动排序。
  • 键唯一:每个键在映射中是唯一的。
  • 高效查找:支持对键的高效查找。

核心点

  • 有序映射:使用红黑树实现,保证键值对的有序性和查找效率。
  • 唯一键:自动去重,保证键的唯一性。

实现

#include <iostream>
#include <map>

void mapExample()
{
    std::map<int, std::string> m;

    // 添加键值对
    m[1] = "one";
    m[2] = "two";
    m[3] = "three";

    // 迭代访问
    for(const auto& pair : m)
    {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // 查找键值对
    auto it = m.find(2);
    if(it != m.end())
    {
        std::cout << "Element found: " << it->first << ": " << it->second << std::endl;
    }
    else
    {
        std::cout << "Element not found" << std::endl;
    }
}

适用场景

  • 需要存储键值对并根据键进行排序的场景。
  • 需要高效查找键的场景。

代码解析

  1. operator[]:在映射中添加或访问键值对。
  2. find:在映射中查找键。
  3. 迭代访问:使用范围基于(range-based)for循环迭代访问键值对。

6. 无序集合(Unordered Set)

概念

std::unordered_set 是一个无序集合,存储唯一的元素并使用哈希表进行管理。

特点

  • 无序:元素没有特定顺序。
  • 唯一性:集合中的元素是唯一的。
  • 高效查找:使用哈希表实现,对元素进行高效查找。

核心点

  • 无序集合:使用哈希表实现,保证元素的唯一性和查找效率。
  • 唯一性:自动去重,保证元素的唯一性。

实现

#include <iostream>
#include <unordered_set>

void unorderedSetExample()
{
    std::unordered_set<int> us;

    // 添加元素
    us.insert(3);
    us.insert(1);
    us.insert(2);
    us.insert(2); // 重复元素插入无效

    // 迭代访问
    for(const auto& elem : us)
    {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 查找元素
    auto it = us.find(2);
    if(it != us.end())
    {
        std::cout << "Element found: " << *it << std::endl;
    }
    else
    {
        std::cout << "Element not found" << std::endl;
    }
}

适用场景

  • 需要存储唯一且无序的元素集合。
  • 需要高效查找元素的场景。

代码解析

  1. insert:在集合中添加元素,自动去重。
  2. find:在集合中查找元素。
  3. 迭代访问:使用范围基于(range-based)for循环迭代访问元素。

7. 无序映射(Unordered Map)

概念

std::unordered_map 是一个无序映射,存储键值对,并使用哈希表进行管理。

特点

  • 无序:键值对没有特定顺序。
  • 键唯一:每个键在映射中是唯一的。
  • 高效查找:使用哈希表实现,对键进行高效查找。

核心点

  • 无序映射:使用哈希表实现,保证键的唯一性和查找效率。
  • 唯一键:自动去重,保证键的唯一性。

实现

#include <iostream>
#include <unordered_map>

void unorderedMapExample()
{
    std::unordered_map<int, std::string> um;

    // 添加键值对
    um[1] = "one";
    um[2] = "two";
    um[3] = "three";

    // 迭代访问
    for(const auto& pair : um)
    {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // 查找键值对
    auto it = um.find(2);
    if(it != um.end())
    {
        std::cout << "Element found: " << it->first << ": " << it->second << std::endl;
    }
    else
    {
        std::cout << "Element not found" << std::endl;
    }
}

适用场景

  • 需要存储键值对并使用哈希表进行管理的场景。
  • 需要高效查找键的场景。

代码解析

  1. operator[]:在映射中添加或访问键值对。
  2. find:在映射中查找键。
  3. 迭代访问:使用范围基于(range-based)for循环迭代访问键值对。

8. 栈(Stack)

概念

std::stack 是一个适配器容器,提供后进先出(LIFO)的数据结构。

特点

  • LIFO:后进先出顺序。
  • 适配器容器:通常基于 std::deque 或 std::vector 实现。

核心点

  • LIFO 数据结构:提供 pushpop 和 top 方法。
  • 适配器模式:基于其他容器实现。

实现

#include <iostream>
#include <stack>

void stackExample()
{
    std::stack<int> st;

    // 添加元素
    st.push(1);
    st.push(2);
    st.push(3);

    // 访问栈顶元素
    std::cout << "Top element: " << st.top() << std::endl;

    // 移除栈顶元素
    st.pop();
    std::cout << "Top element after pop: " << st.top() << std::endl;
}

适用场景

  • 需要后进先出(LIFO)数据结构的场景,如递归调用、表达式求值等。

代码解析

  1. push:在栈顶添加元素。
  2. pop:移除栈顶元素。
  3. top:访问栈顶元素。

9. 队列(Queue)

概念

std::queue 是一个适配器容器,提供先进先出(FIFO)的数据结构。

特点

  • FIFO:先进先出顺序。
  • 适配器容器:通常基于 std::deque 实现。

核心点

  • FIFO 数据结构:提供 pushpop 和 front 方法。
  • 适配器模式:基于其他容器实现。

实现

#include <iostream>
#include <queue>

void queueExample()
{
    std::queue<int> q;

    // 添加元素
    q.push(1);
    q.push(2);
    q.push(3);

    // 访问队首元素
    std::cout << "Front element: " << q.front() << std::endl;

    // 移除队首元素
    q.pop();
    std::cout << "Front element after pop: " << q.front() << std::endl;
}

适用场景

  • 需要先进先出(FIFO)数据结构的场景,如任务调度、消息队列等。

代码解析

  1. push:在队列末尾添加元素。
  2. pop:移除队首元素。
  3. front:访问队首元素。

10. 优先队列(Priority Queue)

概念

std::priority_queue 是一个适配器容器,提供按优先级排序的队列。

特点

  • 优先级排序:元素按照优先级排序。
  • 适配器容器:通常基于 std::vector 和堆算法实现。

核心点

  • 优先级数据结构:提供 pushpop 和 top 方法。
  • 适配器模式:基于其他容器和算法实现。

实现

#include <iostream>
#include <queue>
#include <vector>

void priorityQueueExample()
{
    std::priority_queue<int, std::vector<int>> pq;

    // 添加元素
    pq.push(1);
    pq.push(3);
    pq.push(2);

    // 访问最高优先级元素
    std::cout << "Top element: " << pq.top() << std::endl;

    // 移除最高优先级元素
    pq.pop();
    std::cout << "Top element after pop: " << pq.top() << std::endl;
}

适用场景

  • 需要按优先级处理元素的场景,如任务调度、A*算法等。

代码解析

  1. push:在优先队列中添加元素。
  2. pop:移除最高优先级元素。
  3. top:访问最高优先级元素。

总结

        本文详细介绍了 C++ STL 各种常用容器,包括向量(Vector)、双端队列(Deque)、列表(List)、集合(Set)、映射(Map)、无序集合(Unordered Set)、无序映射(Unordered Map)、栈(Stack)、队列(Queue)和优先队列(Priority Queue)。每种容器的概念、特点、核心点、实现方法、适用场景以及经典示例代码和详细解析都进行了深入讲解。

        通过对这些容器的学习和应用,开发者可以更好地应对软件开发中的复杂问题,提高代码的质量和开发效率,充分发挥

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

猿享天开

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值