Bootstrap

C++容器

C++ 标准库(STL,Standard Template Library)提供了一系列容器,这些容器被划分为三大类:顺序容器有序容器(关联容器)和无序容器(散列容器)。


一、顺序容器

顺序容器用于线性存储数据,主要包含连续存储和链式存储两种方式。

1. 连续存储容器

这些容器在内存中是连续排列的,支持快速随机访问,但插入和删除操作效率较低。

  • array(静态数组)
    特点:

    • 长度固定,无法动态扩展。
    • 存储在栈中,开销低。
    • 支持随机访问,查找效率高。

    示例代码:

    #include <array>
    #include <iostream>
    using namespace std;
    
    int main() {
        array<int, 5> arr = {1, 2, 3, 4, 5};
        for (int i = 0; i < arr.size(); ++i) {
            cout << arr[i] << " ";
        }
        return 0;
    }
    
  • vector(动态数组)
    特点:

    • 支持动态扩展,必要时自动重新分配内存。
    • 插入元素通常只能在尾部(push_back),中间插入效率低。
    • 动态扩展时会有重新分配内存的开销。

    示例代码:

    #include <vector>
    #include <iostream>
    using namespace std;
    
    int main() {
        vector<int> vec = {1, 2, 3};
        vec.push_back(4); // 在尾部插入
        for (int v : vec) {
            cout << v << " ";
        }
        return 0;
    }
    
  • deque(双端队列)
    特点:

    • 支持在头部和尾部高效插入和删除操作。
    • 动态扩展,不需要像 vector 一样频繁拷贝内存。

    示例代码:

    #include <deque>
    #include <iostream>
    using namespace std;
    
    int main() {
        deque<int> dq = {1, 2, 3};
        dq.push_front(0); // 在头部插入
        dq.push_back(4);  // 在尾部插入
        for (int v : dq) {
            cout << v << " ";
        }
        return 0;
    }
    
2. 链式存储容器

这些容器使用指针连接元素,存储位置不连续,插入和删除效率高,但查找效率低。

  • list(双向链表)
    特点:

    • 任意位置插入和删除效率高。
    • 不支持随机访问,需要遍历。

    示例代码:

    #include <list>
    #include <iostream>
    using namespace std;
    
    int main() {
        list<int> lst = {1, 2, 3};
        lst.push_back(4);  // 在尾部插入
        lst.push_front(0); // 在头部插入
        for (int v : lst) {
            cout << v << " ";
        }
        return 0;
    }
    
  • forward_list(单向链表)
    特点:

    • 单向遍历,只能从头到尾。
    • 更适合占用内存较小的场景。

二、关联容器

关联容器基于红黑树结构实现,分为有序容器和无序容器。关联容器中的元素有键值对的概念,操作时需定义比较函数或散列函数。

1. 有序容器

有序容器会对键值自动排序,插入和删除的代价较高,但查找效率较高(对数时间复杂度)。

  • set / multiset(集合)
    特点:

    • set 中元素不能重复,multiset 中允许重复元素。
    • 元素会自动排序。

    示例代码:

    #include <set>
    #include <iostream>
    using namespace std;
    
    int main() {
        set<int> s = {3, 1, 4};
        s.insert(2); // 插入元素
        for (int v : s) {
            cout << v << " "; // 输出为:1 2 3 4
        }
        return 0;
    }
    
  • map / multimap(关联数组/字典)
    特点:

    • map 中键值唯一,multimap 中键值可以重复。
    • 按键排序,支持高效查找。

    示例代码:

    #include <map>
    #include <iostream>
    using namespace std;
    
    int main() {
        map<string, int> m;
        m["apple"] = 3;
        m["banana"] = 5;
        for (auto &[key, value] : m) {
            cout << key << ": " << value << endl;
        }
        return 0;
    }
    
2. 无序容器

无序容器基于**散列表(哈希表)**实现,支持高效的插入和查找操作(常数时间复杂度)。

  • unordered_set / unordered_multiset
    示例代码:

    #include <unordered_set>
    #include <iostream>
    using namespace std;
    
    int main() {
        unordered_set<int> us = {1, 2, 3};
        us.insert(4); // 插入元素
        for (int v : us) {
            cout << v << " "; // 输出顺序可能是随机的
        }
        return 0;
    }
    
  • unordered_map / unordered_multimap
    示例代码:

    #include <unordered_map>
    #include <iostream>
    using namespace std;
    
    int main() {
        unordered_map<string, int> um;
        um["apple"] = 3;
        um["banana"] = 5;
        for (auto &[key, value] : um) {
            cout << key << ": " << value << endl; // 顺序可能是随机的
        }
        return 0;
    }
    

三、容器选择建议

  1. 优先选择 arrayvector

    • 速度快,内存开销低。
  2. 插入和删除频繁时,选择 listdeque

  3. 需要排序的场景:选择 setmap

  4. 无需排序且查找频繁:选择 unordered_setunordered_map


四、注意事项

  1. 自定义比较函数
    对于有序容器,需要定义比较规则。例如:

    set<int, greater<int>> s = {1, 2, 3}; // 降序排列
    
  2. 散列函数
    对于无序容器,可自定义哈希函数。例如:

    struct MyHash {
        size_t operator()(const int &key) const {
            return key % 10;
        }
    };
    unordered_map<int, string, MyHash> um;
    
;