C++ STL标准库

梦想不会自己发光,真正闪耀的是那个为梦狂奔的你。献给知行的孩子们!(Eric.He著)


  本教程将从 C++ STL 标准库的核心概念、六大组件、各类容器到常用算法,全面拆解 STL 的核心用法,帮助你掌握这一提升 C++ 编程效率的核心工具。

教程目录导航

一、STL标准库核心概述

1.1 STL基本定义

STL(Standard Template Library,标准模板库)是 C++ 标准库的核心组成部分,是一套通用的模板化数据结构和算法库。它将数据结构与算法分离,通过模板实现代码复用,大幅提升 C++ 编程效率和代码可维护性。

STL 的核心设计理念是:数据结构和算法的分离与泛化,即算法不依赖具体的数据结构,数据结构也不依赖具体的算法,通过迭代器(Iterator)作为两者的桥梁。

1.2 STL六大组件简介

组件名称 核心作用 典型示例
容器(Container) 存储数据的模板化数据结构 vector、list、set、map、queue、stack
算法(Algorithm) 操作容器中数据的通用算法 sort、find、reverse、unique、max_element
迭代器(Iterator) 连接容器与算法的"桥梁",遍历容器元素 iterator、const_iterator、reverse_iterator
仿函数(Functor) 重载()运算符的类/结构体,替代函数指针 less<>、greater<>、自定义比较仿函数
适配器(Adapter) 封装已有组件,改变其接口或行为 queue(基于deque)、stack(基于deque)
分配器(Allocator) 管理容器内存的分配与释放 std::allocator(默认分配器)

二、序列式容器

序列式容器(Sequence Container)按插入顺序存储元素,元素可通过索引访问,核心特点是元素有序且可重复。

2.1 动态数组vector

vector 是基于动态数组实现的序列式容器,支持随机访问,尾部插入/删除效率高,中间插入/删除效率低(需移动元素)。

核心特性:

示例:vector基本使用


#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 1. 创建vector容器
    vector<int> vec;  // 空vector
    vector<int> vec2(5, 10);  // 5个元素,每个元素值为10
    vector<int> vec3 = {1, 2, 3, 4, 5};  // 初始化列表
    
    // 2. 插入元素
    vec.push_back(1);  // 尾部插入
    vec.push_back(2);
    vec.insert(vec.begin() + 1, 3);  // 在索引1位置插入3
    
    // 3. 访问元素
    cout << "vec[0] = " << vec[0] << endl;  // 直接访问(无越界检查)
    cout << "vec.at(1) = " << vec.at(1) << endl;  // 安全访问(有越界检查)
    cout << "第一个元素:" << vec.front() << endl;
    cout << "最后一个元素:" << vec.back() << endl;
    
    // 4. 遍历元素
    cout << "\n遍历vec:";
    for (int i = 0; i < vec.size(); i++) {
        cout << vec[i] << " ";
    }
    cout << endl;
    
    // 迭代器遍历
    cout << "迭代器遍历:";
    for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
    
    // 5. 删除元素
    vec.pop_back();  // 删除尾部元素
    vec.erase(vec.begin() + 1);  // 删除索引1位置的元素
    
    // 6. 其他常用操作
    cout << "\nvec大小:" << vec.size() << endl;
    cout << "vec容量:" << vec.capacity() << endl;
    vec.resize(5);  // 调整大小为5
    vec.clear();  // 清空所有元素
    cout << "清空后大小:" << vec.size() << endl;
    
    return 0;
}
        

2.2 双向队列deque

deque(Double-Ended Queue)是双向队列,支持头部/尾部高效插入/删除,也支持随机访问,内存由多个连续块组成。

核心特性:

示例:deque基本使用


#include <iostream>
#include <deque>
using namespace std;

int main() {
    deque dq;
    
    // 1. 插入元素
    dq.push_back(10);  // 尾部插入
    dq.push_back(20);
    dq.push_front(5);  // 头部插入
    dq.push_front(1);
    
    // 2. 访问元素
    cout << "dq[1] = " << dq[1] << endl;
    cout << "头部元素:" << dq.front() << endl;
    cout << "尾部元素:" << dq.back() << endl;
    
    // 3. 遍历
    cout << "\n遍历deque:";
    for (deque<int>::iterator it = dq.begin(); it != dq.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
    
    // 4. 删除元素
    dq.pop_front();  // 删除头部
    dq.pop_back();   // 删除尾部
    
    cout << "删除后遍历:";
    for (int num : dq) {  // 范围for遍历
        cout << num << " ";
    }
    cout << endl;
    
    return 0;
}
        

2.3 双向链表list

list 是双向链表实现的序列式容器,不支持随机访问,但任意位置插入/删除效率高(O(1))。

核心特性:

示例:list基本使用


#include <iostream>
#include <list>
using namespace std;

int main() {
    list lst = {3, 1, 4, 2, 5};
    
    // 1. 插入元素
    lst.push_back(6);
    lst.push_front(0);
    lst.insert(++lst.begin(), 10);  // 在第二个位置插入10
    
    // 2. 遍历
    cout << "遍历list:";
    for (int num : lst) {
        cout << num << " ";
    }
    cout << endl;
    
    // 3. 排序、反转
    lst.sort();  // 升序排序
    cout << "排序后:";
    for (int num : lst) {
        cout << num << " ";
    }
    cout << endl;
    
    lst.reverse();  // 反转
    cout << "反转后:";
    for (int num : lst) {
        cout << num << " ";
    }
    cout << endl;
    
    // 4. 删除元素
    lst.pop_front();
    lst.pop_back();
    lst.remove(2);  // 删除所有值为2的元素
    
    cout << "删除后:";
    for (int num : lst) {
        cout << num << " ";
    }
    cout << endl;
    
    return 0;
}
        

三、关联式容器

关联式容器(Associative Container)基于键(Key)存储元素,元素自动排序,不支持随机访问,核心特点是查找效率高(O(logn))。

3.1 集合set

set 是有序不重复的集合,基于红黑树实现,键与值相同,自动按升序排序。

核心特性:

示例:set基本使用


#include <iostream>
#include <set>
using namespace std;

int main() {
    // 1. 创建set(默认升序)
    set<int> s;
    // 降序set
    set<int, greater<int>> s2;
    
    // 2. 插入元素
    s.insert(5);
    s.insert(2);
    s.insert(8);
    s.insert(2);  // 重复元素,插入失败
    
    s2.insert(5);
    s2.insert(2);
    s2.insert(8);
    
    // 3. 遍历
    cout << "升序set:";
    for (int num : s) {
        cout << num << " ";
    }
    cout << endl;
    
    cout << "降序set:";
    for (int num : s2) {
        cout << num << " ";
    }
    cout << endl;
    
    // 4. 查找元素
    auto it = s.find(5);
    if (it != s.end()) {
        cout << "\n找到元素:" << *it << endl;
    }
    
    // 统计元素个数(set中只能是0或1)
    cout << "元素2的个数:" << s.count(2) << endl;
    
    // 5. 删除元素
    s.erase(2);  // 删除值为2的元素
    s.erase(s.begin());  // 删除第一个元素
    
    cout << "删除后set:";
    for (int num : s) {
        cout << num << " ";
    }
    cout << endl;
    
    return 0;
}
        

3.2 映射map

map 是键值对(key-value)的有序集合,基于红黑树实现,键唯一,自动按键升序排序。

核心特性:

示例:map基本使用


#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    // 1. 创建map(键:字符串,值:整数)
    map<string, int> mp;
    
    // 2. 插入键值对
    mp["张三"] = 90;
    mp["李四"] = 85;
    mp["王五"] = 95;
    mp.insert(pair<string, int>("赵六", 88));  // 插入方式2
    mp.insert({"孙七", 92});  // 插入方式3
    
    // 3. 访问值
    cout << "张三的成绩:" << mp["张三"] << endl;
    // 访问不存在的键,会自动插入该键,值为默认值(0)
    cout << "周八的成绩:" << mp["周八"] << endl;
    
    // 4. 遍历
    cout << "\n遍历map:" << endl;
    for (auto& pair : mp) {
        cout << pair.first << ":" << pair.second << endl;
    }
    
    // 迭代器遍历
    cout << "\n迭代器遍历:" << endl;
    for (map<string, int>::iterator it = mp.begin(); it != mp.end(); it++) {
        cout << it->first << ":" << it->second << endl;
    }
    
    // 5. 查找键
    auto it = mp.find("李四");
    if (it != mp.end()) {
        cout << "\n找到李四:" << it->second << endl;
    }
    
    // 6. 删除键值对
    mp.erase("周八");  // 删除键为"周八"的元素
    mp.erase(mp.begin());  // 删除第一个元素
    
    cout << "\n删除后map:" << endl;
    for (auto& pair : mp) {
        cout << pair.first << ":" << pair.second << endl;
    }
    
    return 0;
}
        

四、容器适配器

容器适配器(Container Adapter)是对已有容器的封装,隐藏底层容器的接口,提供特定的操作接口,核心包括queue(队列)和stack(栈)。

4.1 队列queue

queue 是先进先出(FIFO)的队列,默认基于deque实现,仅支持头部删除、尾部插入。

核心特性:

示例:queue基本使用


#include <iostream>
#include <queue>
using namespace std;

int main() {
    queue<int> q;
    
    // 1. 入队
    q.push(10);
    q.push(20);
    q.push(30);
    
    // 2. 访问元素
    cout << "队头元素:" << q.front() << endl;
    cout << "队尾元素:" << q.back() << endl;
    cout << "队列大小:" << q.size() << endl;
    
    // 3. 出队
    q.pop();  // 删除队头
    
    cout << "\n出队后队头:" << q.front() << endl;
    cout << "队列是否为空:" << (q.empty() ? "是" : "否") << endl;
    
    // 遍历(需逐个出队)
    cout << "\n遍历队列:";
    while (!q.empty()) {
        cout << q.front() << " ";
        q.pop();
    }
    cout << endl;
    
    return 0;
}
        

4.2 栈stack

stack 是后进先出(LIFO)的栈,默认基于deque实现,仅支持顶部插入、顶部删除。

核心特性:

示例:stack基本使用


#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack st;
    
    // 1. 入栈
    st.push(1);
    st.push(2);
    st.push(3);
    
    // 2. 访问元素
    cout << "栈顶元素:" << st.top() << endl;
    cout << "栈大小:" << st.size() << endl;
    
    // 3. 出栈
    st.pop();  // 删除栈顶
    
    cout << "\n出栈后栈顶:" << st.top() << endl;
    cout << "栈是否为空:" << (st.empty() ? "是" : "否") << endl;
    
    // 遍历(需逐个出栈)
    cout << "\n遍历栈:";
    while (!st.empty()) {
        cout << st.top() << " ";
        st.pop();
    }
    cout << endl;
    
    return 0;
}
        

五、STL常用算法

STL算法库(<algorithm>)提供了大量通用算法,适用于各类容器,算法通过迭代器操作容器元素,不依赖具体容器类型。

5.1 排序算法sort

sort 是基于快速排序的优化排序算法,默认升序排序,支持自定义比较规则,时间复杂度O(nlogn)。

示例:sort算法使用


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 自定义降序比较函数
bool cmp(int a, int b) {
    return a > b;
}

int main() {
    vector<int> vec = {5, 2, 9, 1, 5, 6};
    
    // 1. 默认升序排序
    sort(vec.begin(), vec.end());
    cout << "升序排序:";
    for (int num : vec) {
        cout << num << " ";
    }
    cout << endl;
    
    // 2. 降序排序(自定义比较函数)
    sort(vec.begin(), vec.end(), cmp);
    cout << "降序排序(函数):";
    for (int num : vec) {
        cout << num << " ";
    }
    cout << endl;
    
    // 3. 降序排序(仿函数)
    sort(vec.begin(), vec.end(), greater<int>());
    cout << "降序排序(仿函数):";
    for (int num : vec) {
        cout << num << " ";
    }
    cout << endl;
    
    return 0;
}
        

5.2 二分查找lower_bound/upper_bound

二分查找算法要求容器已排序,lower_bound 返回第一个≥目标值的迭代器,upper_bound 返回第一个>目标值的迭代器。

示例:二分查找算法使用


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> vec = {1, 3, 5, 5, 7, 9};
    
    // 1. lower_bound:第一个≥5的元素
    auto it1 = lower_bound(vec.begin(), vec.end(), 5);
    if (it1 != vec.end()) {
        cout << "lower_bound(5):" << *it1 << " 索引:" << it1 - vec.begin() << endl;
    }
    
    // 2. upper_bound:第一个>5的元素
    auto it2 = upper_bound(vec.begin(), vec.end(), 5);
    if (it2 != vec.end()) {
        cout << "upper_bound(5):" << *it2 << " 索引:" << it2 - vec.begin() << endl;
    }
    
    // 3. 查找不存在的元素
    auto it3 = lower_bound(vec.begin(), vec.end(), 6);
    if (it3 == vec.end()) {
        cout << "未找到6,插入位置:" << it3 - vec.begin() << endl;
    }
    
    return 0;
}
        

5.3 排列算法next_permutation/prev_permutation

next_permutation 生成当前序列的下一个字典序排列,prev_permutation 生成上一个字典序排列,返回bool值表示是否生成成功。

示例:排列算法使用


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> vec = {1, 2, 3};
    
    cout << "所有排列:" << endl;
    do {
        for (int num : vec) {
            cout << num << " ";
        }
        cout << endl;
    } while (next_permutation(vec.begin(), vec.end()));
    
    // 重置为降序,生成上一个排列
    vector<int> vec2 = {3, 2, 1};
    cout << "\n上一个排列:" << endl;
    if (prev_permutation(vec2.begin(), vec2.end())) {
        for (int num : vec2) {
            cout << num << " ";
        }
    }
    cout << endl;
    
    return 0;
}
        

5.4 反转算法reverse

reverse 反转容器中指定区间的元素顺序,时间复杂度O(n)。

示例:reverse算法使用


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> vec = {1, 2, 3, 4, 5};
    
    cout << "反转前:";
    for (int num : vec) {
        cout << num << " ";
    }
    cout << endl;
    
    // 反转整个容器
    reverse(vec.begin(), vec.end());
    cout << "反转后:";
    for (int num : vec) {
        cout << num << " ";
    }
    cout << endl;
    
    // 反转部分区间(索引1-3)
    reverse(vec.begin() + 1, vec.begin() + 4);
    cout << "反转部分区间后:";
    for (int num : vec) {
        cout << num << " ";
    }
    cout << endl;
    
    return 0;
}
        

5.5 去重算法unique

unique 移除容器中连续的重复元素,返回去重后最后一个元素的迭代器,需配合erase删除冗余元素,使用前需排序(否则仅去重连续重复)。

示例:unique算法使用


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> vec = {1, 2, 2, 3, 3, 3, 4};
    
    cout << "去重前:";
    for (int num : vec) {
        cout << num << " ";
    }
    cout << endl;
    
    // 去重(仅移除连续重复)
    auto it = unique(vec.begin(), vec.end());
    // 删除冗余元素
    vec.erase(it, vec.end());
    
    cout << "去重后:";
    for (int num : vec) {
        cout << num << " ";
    }
    cout << endl;
    
    // 非连续重复需先排序
    vector<int> vec2 = {2, 1, 2, 3, 1, 3};
    sort(vec2.begin(), vec2.end());
    vec2.erase(unique(vec2.begin(), vec2.end()), vec2.end());
    
    cout << "排序后去重:";
    for (int num : vec2) {
        cout << num << " ";
    }
    cout << endl;
    
    return 0;
}
        

5.6 最值算法min_element/max_element

min_element 返回容器中最小值的迭代器,max_element 返回最大值的迭代器,时间复杂度O(n)。

示例:最值算法使用


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> vec = {5, 2, 9, 1, 7, 3};
    
    // 最小值
    auto min_it = min_element(vec.begin(), vec.end());
    cout << "最小值:" << *min_it << " 索引:" << min_it - vec.begin() << endl;
    
    // 最大值
    auto max_it = max_element(vec.begin(), vec.end());
    cout << "最大值:" << *max_it << " 索引:" << max_it - vec.begin() << endl;
    
    return 0;
}
        

六、注意事项

七、总结

本教程从 STL 核心概念、六大组件到各类容器和常用算法,全面拆解了 STL 的核心用法。掌握 STL 是提升 C++ 编程效率和代码质量的关键,也是学习高级数据结构和算法的重要基础。


返回顶部