C++ 常用STL底层原理

STL

1. std::vector

在这里插入图片描述

底层原理:std::vector 是一个动态数组。它在内存中分配一块连续的存储空间来存储元素。随着元素数量的增加,如果存储空间不够用,vector 会分配一块更大的内存,并将现有元素复制到新内存块中。通常,vector 的容量会按一定比例(通常是两倍)扩展,以减少频繁的内存分配和复制操作。
优点:快速的随机访问(O(1))、尾部插入和删除操作(均摊 O(1))。
缺点:当容量需要扩展时,可能会发生较慢的重新分配和元素复制。

内部结构示意

template <typename T, typename Allocator = std::allocator<T>>
class vector {
private:
    T* data;              // 指向元素存储区域的指针
    size_type size;       // 当前存储的元素数量
    size_type capacity;   // 当前分配的最大存储容量
    Allocator allocator;  // 用于管理内存的分配器

    // ...
};

2. std::list

在这里插入图片描述

底层原理:std::list 是一个双向链表。每个元素都存储在一个节点中,节点包含数据和指向前后节点的指针。链表的元素在内存中不需要是连续的,因此插入和删除元素非常高效(O(1)),但不支持快速随机访问(O(n))。
优点:高效的插入和删除操作,尤其是在中间位置。
缺点:较慢的随机访问,不适合需要频繁索引访问的场景。

内部结构示意

template<typename T>
struct Node {
    T data;        // 节点存储的数据
    Node* prev;    // 指向前一个节点的指针
    Node* next;    // 指向后一个节点的指针
};

template<typename T>
class list {
private:
    Node<T>* head;   // 指向链表的头节点
    Node<T>* tail;   // 指向链表的尾节点
    size_t size;     // 链表中的元素数量
    // 其他成员...
};

3. std::deque

在这里插入图片描述
deque内部工作原理:
deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据。
中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间。
在这里插入图片描述

底层原理:std::deque(双端队列)实现为一组连续的小块内存(通常称为块或缓冲区),这些块通过指针数组连接在一起。deque 支持双端操作,因此可以在两端高效地插入和删除元素。随机访问的时间复杂度为 O(1)。
优点:快速的双端插入和删除、快速的随机访问。
缺点:相比 vector,内存占用略高,因为需要额外的指针来管理块。

内部结构示意

template <typename T, typename Allocator = std::allocator<T>>
class deque {
private:
    typedef T* pointer; // 定义指向元素的指针类型
    pointer* map;       // 内存块数组(map),存储指向每个内存块的指针
    // 头部和尾部指针
    pointer start;     
    pointer finish;    

    size_t map_size;     // 当前容量和块的大小
    static const size_t block_size = 512; // 内存块大小
    Allocator allocator; // 分配器,用于分配内存
}

4. std::stack

在这里插入图片描述

底层原理:std::stack 是一种适配器容器,通常基于 std::deque 或 std::vector 实现。它提供了一种后进先出(LIFO)的数据结构,支持 push、pop、top 等操作。
优点:简单的 LIFO 操作,底层实现可以灵活选择。
缺点:只提供有限的接口,无法遍历或随机访问。

5. std::queue

在这里插入图片描述

底层原理:std::queue 是一种适配器容器,通常基于 std::deque 实现。它提供了一种先进先出(FIFO)的数据结构,支持 push(入队)、pop(出队)、front(获取队头)等操作。
优点:简单的 FIFO 操作,底层实现可以灵活选择。
缺点:只提供有限的接口,无法遍历或随机访问。

6. std::priority_queue

底层原理:std::priority_queue 通常使用 std::vector 作为底层容器,并基于二叉堆(通常是最大堆)实现。它允许你高效地访问并删除优先级最高的元素(通常是最大元素)。
优点:支持高效的最大或最小值访问,插入和删除操作的时间复杂度为 O(log n)。
缺点:随机访问和遍历效率低,不适合频繁需要全部元素排序的场景。

7. std::set 和 std::multiset

底层原理:std::set 和 std::multiset 通常基于红黑树实现。红黑树是一种自平衡二叉搜索树,能够保证基本操作(插入、删除、查找)的时间复杂度为 O(log n)。std::set 存储唯一元素,而 std::multiset 允许重复元素。
优点:高效的查找、插入和删除操作,元素自动排序。
缺点:相比于 unordered_set,性能稍差,内存占用稍高。

8. std::map 和 std::multimap

底层原理:std::map 和 std::multimap 也基于红黑树实现。它们存储的是键值对(key-value),std::map 中的键是唯一的,而 std::multimap 允许相同的键出现多次。
优点:高效的键查找、插入和删除操作,键值对按键自动排序。
缺点:相比于 unordered_map,查找和插入性能稍差,内存占用稍高。

部分内部结构示意

template<typename Key, typename T>
struct Node {
    std::pair<const Key, T> data;  // 键值对
    Node* parent;                  // 指向父节点的指针
    Node* left;                    // 指向左子节点的指针
    Node* right;                   // 指向右子节点的指针
    bool color;                    // 节点颜色(红或黑)
};

9. std::unordered_set 和 std::unordered_map

底层原理:std::unordered_set 和 std::unordered_map 基于哈希表实现。哈希表使用哈希函数将键映射到桶中,从而实现常数时间复杂度(O(1))的查找、插入和删除操作。
优点:非常高效的查找、插入和删除操作,适合不需要排序的场景。
缺点:键的顺序不固定,容易受到哈希冲突的影响,性能可能不如红黑树稳定。

10. std::unordered_multiset 和 std::unordered_multimap

底层原理:与 std::unordered_set 和 std::unordered_map 类似,但允许存储重复的元素(unordered_multiset)或重复的键(unordered_multimap)。
优点:与 unordered_set 和 unordered_map 类似,提供高效的查找、插入和删除操作,允许重复元素或键。
缺点:键的顺序不固定,容易受到哈希冲突的影响。

vector 动态数组,list 双向链表,deque 双端队列,stack 栈, queue 队列, map 红黑树(键值对), set 红黑树(不允许元素重复)

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值