Skip to content

STL标准模板库

STL(Standard Template Library)是C++标准库的重要组成部分,提供了容器、迭代器、算法和函数对象等组件。本章将详细介绍STL的使用方法。

容器概述

cpp
#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <array>
using namespace std;

/*
 * STL容器分类:
 * 
 * 1. 序列容器(顺序容器)
 *    - vector:动态数组
 *    - deque:双端队列
 *    - list:双向链表
 *    - forward_list:单向链表
 *    - array:固定大小数组
 * 
 * 2. 关联容器
 *    - set/multiset:集合
 *    - map/multimap:映射
 *    - unordered_set/unordered_multiset:哈希集合
 *    - unordered_map/unordered_multimap:哈希映射
 * 
 * 3. 容器适配器
 *    - stack:栈
 *    - queue:队列
 *    - priority_queue:优先队列
 */

int main() {
    // ============ vector ============
    
    vector<int> vec = {1, 2, 3, 4, 5};
    
    // 添加元素
    vec.push_back(6);
    vec.emplace_back(7);  // C++11,更高效
    
    // 访问元素
    cout << "vec[0] = " << vec[0] << endl;
    cout << "vec.at(1) = " << vec.at(1) << endl;  // 带边界检查
    cout << "vec.front() = " << vec.front() << endl;
    cout << "vec.back() = " << vec.back() << endl;
    
    // 大小和容量
    cout << "size = " << vec.size() << endl;
    cout << "capacity = " << vec.capacity() << endl;
    
    // 遍历
    cout << "vector: ";
    for (int n : vec) {
        cout << n << " ";
    }
    cout << endl;
    
    
    // ============ list ============
    
    list<int> lst = {1, 2, 3, 4, 5};
    
    // 在头部和尾部添加
    lst.push_front(0);
    lst.push_back(6);
    
    // 插入
    auto it = lst.begin();
    advance(it, 2);  // 移动迭代器
    lst.insert(it, 100);
    
    cout << "list: ";
    for (int n : lst) {
        cout << n << " ";
    }
    cout << endl;
    
    
    // ============ deque ============
    
    deque<int> dq = {1, 2, 3};
    
    dq.push_front(0);
    dq.push_back(4);
    
    cout << "deque: ";
    for (int n : dq) {
        cout << n << " ";
    }
    cout << endl;
    
    
    // ============ array ============
    
    array<int, 5> arr = {1, 2, 3, 4, 5};
    
    cout << "array: ";
    for (int n : arr) {
        cout << n << " ";
    }
    cout << endl;
    
    cout << "array size = " << arr.size() << endl;
    
    return 0;
}

关联容器

cpp
#include <iostream>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
using namespace std;

int main() {
    // ============ set ============
    
    // 自动排序,不允许重复
    set<int> s = {5, 3, 1, 4, 2};
    
    s.insert(6);
    s.insert(3);  // 重复元素不会被插入
    
    cout << "set: ";
    for (int n : s) {
        cout << n << " ";
    }
    cout << endl;
    
    // 查找
    if (s.find(3) != s.end()) {
        cout << "找到 3" << endl;
    }
    
    // 统计
    cout << "count(3) = " << s.count(3) << endl;
    
    // multiset:允许重复
    multiset<int> ms = {1, 2, 2, 3, 3, 3};
    cout << "multiset count(3) = " << ms.count(3) << endl;
    
    
    // ============ map ============
    
    // 键值对,按键排序
    map<string, int> scores;
    
    // 插入
    scores["张三"] = 90;
    scores["李四"] = 85;
    scores.insert({"王五", 95});
    scores.emplace("赵六", 88);
    
    // 访问
    cout << "\n张三的分数: " << scores["张三"] << endl;
    
    // 遍历
    cout << "map内容:" << endl;
    for (const auto& pair : scores) {
        cout << "  " << pair.first << ": " << pair.second << endl;
    }
    
    // 查找
    auto it = scores.find("李四");
    if (it != scores.end()) {
        cout << "找到李四,分数: " << it->second << endl;
    }
    
    // multimap:允许重复键
    multimap<string, int> mm;
    mm.insert({"课程", 90});
    mm.insert({"课程", 85});
    cout << "multimap count(\"课程\") = " << mm.count("课程") << endl;
    
    
    // ============ unordered_set ============
    
    // 哈希实现,不排序,查找更快
    unordered_set<int> us = {5, 3, 1, 4, 2};
    
    us.insert(6);
    
    cout << "\nunordered_set: ";
    for (int n : us) {
        cout << n << " ";
    }
    cout << endl;
    
    // 平均O(1)查找
    if (us.find(3) != us.end()) {
        cout << "找到 3" << endl;
    }
    
    
    // ============ unordered_map ============
    
    unordered_map<string, int> um;
    
    um["apple"] = 1;
    um["banana"] = 2;
    um["orange"] = 3;
    
    cout << "\nunordered_map内容:" << endl;
    for (const auto& pair : um) {
        cout << "  " << pair.first << ": " << pair.second << endl;
    }
    
    return 0;
}

迭代器

cpp
#include <iostream>
#include <vector>
#include <list>
#include <iterator>
using namespace std;

int main() {
    vector<int> vec = {1, 2, 3, 4, 5};
    
    // ============ 迭代器类型 ============
    
    // 正向迭代器
    cout << "正向遍历: ";
    for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
    
    // 反向迭代器
    cout << "反向遍历: ";
    for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {
        cout << *rit << " ";
    }
    cout << endl;
    
    // 常量迭代器
    cout << "常量迭代器: ";
    for (auto cit = vec.cbegin(); cit != vec.cend(); ++cit) {
        cout << *cit << " ";
        // *cit = 10;  // 错误:不能修改
    }
    cout << endl;
    
    // C++11:范围for循环
    cout << "范围for: ";
    for (int n : vec) {
        cout << n << " ";
    }
    cout << endl;
    
    
    // ============ 迭代器操作 ============
    
    auto it = vec.begin();
    
    // 前进
    advance(it, 2);  // it指向第3个元素
    cout << "\nadvance后: " << *it << endl;
    
    // 距离
    auto it2 = vec.end();
    cout << "distance: " << distance(vec.begin(), it2) << endl;
    
    // 下一个
    auto nextIt = next(it);
    cout << "next: " << *nextIt << endl;
    
    // 上一个
    auto prevIt = prev(it);
    cout << "prev: " << *prevIt << endl;
    
    
    // ============ 插入迭代器 ============
    
    vector<int> v1 = {1, 2, 3};
    vector<int> v2 = {4, 5, 6};
    
    // back_inserter:在末尾插入
    copy(v2.begin(), v2.end(), back_inserter(v1));
    
    cout << "\nback_inserter后: ";
    for (int n : v1) {
        cout << n << " ";
    }
    cout << endl;
    
    // front_inserter:在开头插入(适用于list、deque)
    list<int> lst = {1, 2, 3};
    list<int> lst2 = {4, 5, 6};
    copy(lst2.begin(), lst2.end(), front_inserter(lst));
    
    cout << "front_inserter后: ";
    for (int n : lst) {
        cout << n << " ";
    }
    cout << endl;
    
    // inserter:在指定位置插入
    vector<int> v3 = {1, 2, 5, 6};
    vector<int> v4 = {3, 4};
    auto insertIt = v3.begin() + 2;
    copy(v4.begin(), v4.end(), inserter(v3, insertIt));
    
    cout << "inserter后: ";
    for (int n : v3) {
        cout << n << " ";
    }
    cout << endl;
    
    
    // ============ 流迭代器 ============
    
    // 输出流迭代器
    cout << "\n流迭代器输出: ";
    copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
    cout << endl;
    
    return 0;
}

算法

cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>
using namespace std;

int main() {
    vector<int> vec = {5, 2, 8, 1, 9, 3, 7, 4, 6};
    
    // ============ 排序算法 ============
    
    // sort:排序
    sort(vec.begin(), vec.end());
    cout << "升序: ";
    for (int n : vec) cout << n << " ";
    cout << endl;
    
    // 降序
    sort(vec.begin(), vec.end(), greater<int>());
    cout << "降序: ";
    for (int n : vec) cout << n << " ";
    cout << endl;
    
    // partial_sort:部分排序
    vector<int> v1 = {5, 2, 8, 1, 9, 3, 7, 4, 6};
    partial_sort(v1.begin(), v1.begin() + 3, v1.end());
    cout << "部分排序(前3个): ";
    for (int n : v1) cout << n << " ";
    cout << endl;
    
    // stable_sort:稳定排序
    // nth_element:第n个元素
    
    // ============ 查找算法 ============
    
    vector<int> v2 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    
    // find:查找元素
    auto it = find(v2.begin(), v2.end(), 5);
    if (it != v2.end()) {
        cout << "\n找到5,位置: " << (it - v2.begin()) << endl;
    }
    
    // binary_search:二分查找(需要已排序)
    bool found = binary_search(v2.begin(), v2.end(), 5);
    cout << "binary_search(5): " << (found ? "找到" : "未找到") << endl;
    
    // lower_bound:第一个 >= 目标的位置
    auto lb = lower_bound(v2.begin(), v2.end(), 5);
    cout << "lower_bound(5): " << (lb - v2.begin()) << endl;
    
    // upper_bound:第一个 > 目标的位置
    auto ub = upper_bound(v2.begin(), v2.end(), 5);
    cout << "upper_bound(5): " << (ub - v2.begin()) << endl;
    
    // find_if:条件查找
    auto it2 = find_if(v2.begin(), v2.end(), [](int n) { return n > 5; });
    if (it2 != v2.end()) {
        cout << "第一个大于5的数: " << *it2 << endl;
    }
    
    // ============ 修改算法 ============
    
    vector<int> v3 = {1, 2, 3, 4, 5};
    vector<int> v4(5);
    
    // copy:复制
    copy(v3.begin(), v3.end(), v4.begin());
    
    // transform:变换
    transform(v3.begin(), v3.end(), v4.begin(), [](int n) { return n * 2; });
    cout << "\ntransform后: ";
    for (int n : v4) cout << n << " ";
    cout << endl;
    
    // fill:填充
    fill(v4.begin(), v4.end(), 0);
    
    // replace:替换
    vector<int> v5 = {1, 2, 3, 2, 4, 2, 5};
    replace(v5.begin(), v5.end(), 2, 10);
    cout << "replace后: ";
    for (int n : v5) cout << n << " ";
    cout << endl;
    
    // remove:移除(实际是移动,返回新逻辑末尾)
    v5.erase(remove(v5.begin(), v5.end(), 10), v5.end());
    cout << "remove后: ";
    for (int n : v5) cout << n << " ";
    cout << endl;
    
    // ============ 数值算法 ============
    
    vector<int> v6 = {1, 2, 3, 4, 5};
    
    // accumulate:累加
    int sum = accumulate(v6.begin(), v6.end(), 0);
    cout << "\n累加和: " << sum << endl;
    
    // 带操作的累加
    int product = accumulate(v6.begin(), v6.end(), 1, multiplies<int>());
    cout << "累乘积: " << product << endl;
    
    // adjacent_difference:相邻差
    // inner_product:内积
    // partial_sum:部分和
    
    // ============ 其他算法 ============
    
    // count:计数
    vector<int> v7 = {1, 2, 3, 2, 4, 2, 5};
    int cnt = count(v7.begin(), v7.end(), 2);
    cout << "\n2的个数: " << cnt << endl;
    
    // count_if:条件计数
    cnt = count_if(v7.begin(), v7.end(), [](int n) { return n > 2; });
    cout << "大于2的个数: " << cnt << endl;
    
    // min_element / max_element
    auto minIt = min_element(v7.begin(), v7.end());
    auto maxIt = max_element(v7.begin(), v7.end());
    cout << "最小值: " << *minIt << ", 最大值: " << *maxIt << endl;
    
    // reverse:反转
    reverse(v7.begin(), v7.end());
    cout << "反转后: ";
    for (int n : v7) cout << n << " ";
    cout << endl;
    
    // unique:去重(需要先排序)
    sort(v7.begin(), v7.end());
    v7.erase(unique(v7.begin(), v7.end()), v7.end());
    cout << "去重后: ";
    for (int n : v7) cout << n << " ";
    cout << endl;
    
    return 0;
}

本章小结

本章学习了:

  • 序列容器:vector、list、deque、array
  • 关联容器:set、map、unordered_set、unordered_map
  • 迭代器:正向、反向、插入迭代器、流迭代器
  • 算法:排序、查找、修改、数值算法

下一章,我们将学习异常处理,了解C++的错误处理机制。