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

目录

[1. 向量(Vector)](#1. 向量(Vector))

概念

特点

核心点

实现

适用场景

代码解析

[2. 双端队列(Deque)](#2. 双端队列(Deque))

概念

特点

核心点

实现

适用场景

代码解析

[3. 列表(List)](#3. 列表(List))

概念

特点

核心点

实现

适用场景

代码解析

[4. 集合(Set)](#4. 集合(Set))

概念

特点

核心点

实现

适用场景

代码解析

[5. 映射(Map)](#5. 映射(Map))

概念

特点

核心点

实现

适用场景

代码解析

[6. 无序集合(Unordered Set)](#6. 无序集合(Unordered Set))

概念

特点

核心点

实现

适用场景

代码解析

[7. 无序映射(Unordered Map)](#7. 无序映射(Unordered Map))

概念

特点

核心点

实现

适用场景

代码解析

[8. 栈(Stack)](#8. 栈(Stack))

概念

特点

核心点

实现

适用场景

代码解析

[9. 队列(Queue)](#9. 队列(Queue))

概念

特点

核心点

实现

适用场景

代码解析

[10. 优先队列(Priority Queue)](#10. 优先队列(Priority Queue))

概念

特点

核心点

实现

适用场景

代码解析

总结


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

1. 向量(Vector)

概念

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

特点

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

核心点

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

实现

cpp 复制代码
#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_frontpush_back 方法用于在两端添加元素。
  • 内存管理:使用分段存储来优化内存管理。

实现

cpp 复制代码
#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 是一个双向链表,支持在任意位置高效地插入和删除元素。

特点

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

核心点

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

实现

cpp 复制代码
#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 是一个有序集合,存储唯一的元素并自动对元素进行排序。

特点

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

核心点

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

实现

cpp 复制代码
#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 是一个有序映射,存储键值对,并根据键对元素进行排序。

特点

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

核心点

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

实现

cpp 复制代码
#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 是一个无序集合,存储唯一的元素并使用哈希表进行管理。

特点

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

核心点

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

实现

cpp 复制代码
#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 是一个无序映射,存储键值对,并使用哈希表进行管理。

特点

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

核心点

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

实现

cpp 复制代码
#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::dequestd::vector 实现。

核心点

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

实现

cpp 复制代码
#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 数据结构 :提供 pushpopfront 方法。
  • 适配器模式:基于其他容器实现。

实现

cpp 复制代码
#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 和堆算法实现。

核心点

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

实现

cpp 复制代码
#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)。每种容器的概念、特点、核心点、实现方法、适用场景以及经典示例代码和详细解析都进行了深入讲解。

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

相关推荐
m0_741768851 小时前
使用docker的小例子
运维·docker·容器
C-SDN花园GGbond1 小时前
【探索数据结构与算法】插入排序:原理、实现与分析(图文详解)
c语言·开发语言·数据结构·排序算法
迷迭所归处2 小时前
C++ —— 关于vector
开发语言·c++·算法
架构文摘JGWZ3 小时前
Java 23 的12 个新特性!!
java·开发语言·学习
leon6253 小时前
优化算法(一)—遗传算法(Genetic Algorithm)附MATLAB程序
开发语言·算法·matlab
CV工程师小林3 小时前
【算法】BFS 系列之边权为 1 的最短路问题
数据结构·c++·算法·leetcode·宽度优先
white__ice3 小时前
2024.9.19
c++
天玑y4 小时前
算法设计与分析(背包问题
c++·经验分享·笔记·学习·算法·leetcode·蓝桥杯
锦亦之22334 小时前
QT+OSG+OSG-earth如何在窗口显示一个地球
开发语言·qt
我是苏苏4 小时前
Web开发:ABP框架2——入门级别的增删改查Demo
java·开发语言