C++ 基础

C++ 基础语法、常用库函数和数据结构,算法题解的必备工具

头文件

  • 常用头文件

    头文件核心作用
    #include <iostream>输入输出(cin/cout),算法题最基础的输入输出工具
    #include <vector>动态数组(替代普通数组,无需手动管理内存,算法题中最常用的数据结构)
    #include <algorithm>包含所有标准算法(排序、查找、最值、交换等),算法题的核心库
    #include <string>字符串处理(拼接、查找、截取等)
    #include <cmath>数学函数(绝对值、幂、开方、取整、三角函数等)
    #include <climits>提供系统极值(如 INT_MAX/INT_MIN,避免手动定义最大值 / 最小值)
    #include <queue>队列(queue)、优先队列(priority_queue,常用于堆排序 / 贪心题)
    #include <stack>栈(stack),用于 DFS、括号匹配等题
    #include <map>/<unordered_map>键值对映射(有序 / 无序,统计频率、哈希表场景)
    #include <set>/<unordered_set>集合(有序 / 无重复,去重、查找存在性)
    #include <numeric>数值算法(如累加、累乘,少用但关键场景很方便)

库函数

  • 数值计算(<cmath>)

    • 绝对值:abs()(int)、fabs()(double/float)
    • 取整:floor()(向下取整)、ceil()(向上取整)、round()(四舍五入)
    • 幂 / 开方:pow(a, b)(a 的 b 次方)、sqrt(x)(平方根)、cbrt(x)(立方根)
    • 最值:max(a,b)、min(a,b)(可直接比较两个数,algorithm 库也有)
  • swap():交换两个变量的值

    int a=1, b=2;
    swap(a, b); // a=2, b=1
  • accumulate()(<numeric>):累加容器元素(需指定初始值)

    vector<int> nums = {1,2,3,4};
    int sum = accumulate(nums.begin(), nums.end(), 0); // 1+2+3+4=10
  • reverse()(<algorithm>):反转容器元素顺序

    vector<int> nums = {1,2,3,4};
    reverse(nums.begin(), nums.end()); // 结果:4 3 2 1
    // 也可以反转字符串
    string s = "hello";
    reverse(s.begin(), s.end()); // s 反转
    // 反转部分元素
    vector<int> nums2 = {1,2,3,4,5};
    reverse(nums2.begin() + 1, nums2.end() - 1); // 反转索引1到倒数第二个元素,结果:1 4 3 2 5
    // 反转二维矩阵的行
    vector<vector<int>> matrix = {{1,2,3}, {4,5,6}, {7,8,9}};
    for (auto& row : matrix) {
      reverse(row.begin(), row.end()); // 每行反转,结果:{{3,2,1}, {6,5,4}, {9,8,7}}
    }
  • find():查找元素,返回迭代器(找不到返回 end ())

    vector<int> nums = {1,2,3,4,5};
    auto it = find(nums.begin(), nums.end(), 3);
    if (it != nums.end()) {
        cout << "找到元素,索引:" << it - nums.begin() << endl; // 输出:2
    }
  • binary_search():二分查找(前提:容器已排序),返回 bool 值

    vector<int> nums = {1,2,3,4,5};
    bool exist = binary_search(nums.begin(), nums.end(), 3); // true
  • max_element() / min_element()(<algorithm>):获取容器中最大 / 最小元素的迭代器

    vector<int> nums = {1,2,3,4};
    auto max_it = max_element(nums.begin(), nums.end()); // 指向最大元素4
    auto min_it = min_element(nums.begin(), nums.end()); // 指向最小元素1
    int max_val = *max_it; // 获取最大值4
    int min_val = *min_it; // 获取最小值1
    // 也可以配合自定义比较器获取满足特定条件的最大 / 最小元素
    vector<string> words = {"apple", "banana", "cherry"};
    auto longest_it = max_element(words.begin(), words.end(), [](const string& a, const string& b) {
      return a.length() < b.length(); // 按字符串长度比较,获取最长字符串
    });
  • fill()(<algorithm>):填充容器元素为指定值

    vector<int> nums(5); // 创建一个大小为5的vector,初始值为0
    fill(nums.begin(), nums.end(), 1); // 将所有元素填充为1,结果:1 1 1 1 1
  • count() (<algorithm>):统计容器中某个值出现的次数

    vector<int> nums = {1,2,3,4,5,2};
    int count_2 = count(nums.begin(), nums.end(), 2); // 统计2出现的次数,结果为2
  • count_if()(<algorithm>):统计满足条件的元素个数

    vector<int> nums = {1,2,3,4,5};
    int count_even = count_if(nums.begin(), nums.end(), [](int x) {
      return x % 2 == 0; // 统计偶数的个数
    });
  • sort()(<algorithm>):排序容器元素,默认升序,可自定义比较规则

    vector<int> nums = {5, 2, 9, 1, 5, 6};
    sort(nums.begin(), nums.end()); // 升序排序
    sort(nums.begin(), nums.end(), greater<int>()); // 降序排序
    sort(nums.begin(), nums.end(), [](int a, int b) { return abs(a) < abs(b); }); // 按绝对值排序
    sort(nums.begin(), nums.end(), [](int a, int b) { return a % 10 < b % 10; }); // 按个位数排序
    sort(nums.begin(), nums.end(), [](int a, int b) { return to_string(a) < to_string(b); }); // 按字符串形式排序
    sort(nums.begin(), nums.end(), [](int a, int b) {
      if (a % 2 != b % 2) return a % 2 < b % 2; // 奇数在前偶数在后
      return a < b; // 同为奇数或偶数则升序
    });
    vector<pair<int, int>> pairs = {{1, 2}, {3, 1}, {2, 3}};
    sort(pairs.begin(), pairs.end(), [](const pair<int, int>& p1, const pair<int, int>& p2) {
      if (p1.first != p2.first) return p1.first < p2.first; // 先按第一个元素升序
      return p1.second > p2.second; // 第一个元素相同则按第二个元素降序
    });
    string s = "hello";
    sort(s.begin(), s.end()); // s变为"ehllo"
    sort(s.begin(), s.end(), greater<char>()); // s变为"ollhe"
    sort(s.begin(), s.end(), [](char a, char b) { return tolower(a) < tolower(b); }); // 按字母顺序排序,忽略大小写
    sort(s.begin(), s.end(), [](char a, char b) {
      if (isalpha(a) && isalpha(b)) return tolower(a) < tolower(b); // 字母按字母顺序排序
      if (isalpha(a)) return true; // 字母在前
      if (isalpha(b)) return false; // 字母在前
      return a < b; // 其他字符按 ASCII 码排序
    });
  • stable_sort():稳定排序(保持相等元素的相对顺序),效率略低于 sort

  • unique()(<algorithm>):去除容器中相邻的重复元素(需先排序)

    vector<int> nums = {1,1,2,2,3,3};
    sort(nums.begin(), nums.end()); // 先排序
    auto it = unique(nums.begin(), nums.end()); // 去除相邻重复
    // unique 返回的迭代器指向去重后容器的末尾,需配合 erase 删除多余元素
    nums.erase(it, nums.end()); // 删除多余元素,结果:1 2 3
    // unique() 只去除相邻重复,所以如果不先排序,结果可能不正确
    vector<int> nums2 = {1,2,1,3,2,3};
    auto it2 = unique(nums2.begin(), nums2.end()); // 结果可能是 1 2 1 3 2 3(没有去除重复)
    // unique() 也可以配合自定义比较器去除满足特定条件的元素
    vector<string> words = {"apple", "Apple", "banana", "Banana"};
    sort(words.begin(), words.end(), [](const string& a, const string& b) {
      return tolower(a[0]) < tolower(b[0]); // 按首字母排序,忽略大小写
    });
    auto it3 = unique(words.begin(), words.end(), [](const string& a, const string& b) {
      return tolower(a[0]) == tolower(b[0]); // 去除首字母相同的元素
    });
    words.erase(it3, words.end()); // 结果可能是 "apple" "banana"(去除首字母相同的元素)
    // unique() 也可以配合 lambda 表达式实现更复杂的去重逻辑
    vector<int> nums3 = {1,2,3,4,5};
    auto it4 = unique(nums3.begin(), nums3.end(), [](int a, int b) {
      return (a + b) % 2 == 0; // 去除和为偶数的相邻元素
    });
    nums3.erase(it4, nums3.end()); // 结果可能是 1 2 4(去除和为偶数的相邻元素)
  • lower_bound()/upper_bound():二分查找,返回第一个不小于 / 大于目标值的迭代器(前提:容器已排序)

    vector<int> nums = {1,2,4,4,5};
    auto it1 = lower_bound(nums.begin(), nums.end(), 4); // 指向第一个4
    auto it2 = upper_bound(nums.begin(), nums.end(), 4); // 指向第一个大于4的元素(5)
    int count = it2 - it1; // 统计4的出现次数,结果为2
    // 也可以配合自定义比较器使用
    vector<string> words = {"apple", "banana", "cherry"};
    sort(words.begin(), words.end()); // 先排序
    auto it3 = lower_bound(words.begin(), words.end(), "blueberry"); // 指向第一个不小于"blueberry"的元素("cherry")
    auto it4 = upper_bound(words.begin(), words.end(), "blueberry"); // 指向第一个大于"blueberry"的元素("cherry")
    // 如果容器中没有不小于 / 大于目标值的元素,lower_bound() / upper_bound() 返回 end() 迭代器
    auto it5 = lower_bound(words.begin(), words.end(), "zucchini"); // 指向 end()(没有不小于"zucchini"的元素)
    auto it6 = upper_bound(words.begin(), words.end(), "zucchini"); // 指向 end()(没有大于"zucchini"的元素)
    // 如果容器中所有元素都不小于 / 大于目标值,lower_bound() / upper_bound() 返回 begin() 迭代器
    auto it7 = lower_bound(words.begin(), words.end(), "aardvark"); // 指向 begin()(所有元素都不小于"aardvark")
    auto it8 = upper_bound(words.begin(), words.end(), "aardvark"); // 指向 begin()(所有元素都大于"aardvark")
    // 如果容器未排序,lower_bound() / upper_bound() 的行为未定义,结果可能不正确
    vector<int> unsorted_nums = {5,2,4,1,3};
    auto it9 = lower_bound(unsorted_nums.begin(), unsorted_nums.end(), 3); // 行为未定义,结果可能不正确
    auto it10 = upper_bound(unsorted_nums.begin(), unsorted_nums.end(), 3); // 行为未定义,结果可能不正确
    // lower_bound() / upper_bound() 也可以配合 lambda 表达式实现更复杂的查找逻辑
    vector<int> nums4 = {1,2,3,4,5};
    auto it11 = lower_bound(nums4.begin(), nums4.end(), 0, [](int a, int b) {
      return a < b; // 按照默认的升序比较
    }); // 指向第一个不小于0的元素(1)
    auto it12 = upper_bound(nums4.begin(), nums4.end(), 5, [](int a, int b) {
      return a < b; // 按照默认的升序比较
    }); // 指向第一个大于5的元素(没有,返回 end())
  • next_permutation()/prev_permutation():生成下一个 / 上一个字典序排列

    vector<int> nums = {1,2,3};
    next_permutation(nums.begin(), nums.end()); // 结果:1 3 2
    next_permutation(nums.begin(), nums.end()); // 结果:2 1 3
    prev_permutation(nums.begin(), nums.end()); // 结果:1 3 2
    prev_permutation(nums.begin(), nums.end()); // 结果:1 2 3(回到初始状态)
  • to_string():数字转字符串

     int num = 123;
     string s_num = to_string(num); // "123"
     double pi = 3.14159;
     string s_pi = to_string(pi); // "3.141590"(默认保留6位小数)
     long long big_num = 1234567890123456789LL;
     string s_big_num = to_string(big_num); // "1234567890123456789"
     bool flag = true;
     string s_flag = to_string(flag); // "1"(true 转为 "1",false 转为 "0")
     char c = 'A';
     string s_char(1, c); // char 转 string,结果为 "A"
     string s_bool = to_string(false); // "0"
     string s_num2 = to_string(-456); // "-456"
     string s_num3 = to_string(0); // "0"
     string s_num4 = to_string(3.14); // "3.140000"
     string s_num5 = to_string(2.71828); // "2.718280"
     string s_num6 = to_string(1e-10); // "0.000000"(科学计数法转为小数时可能会丢失精度)
     string s_num7 = to_string(1e10); // "10000000000.000000"(科学计数法转为小数时可能会丢失精度)
     string s_num8 = to_string(1.23456789); // "1.234568"(默认保留6位小数,超出部分会四舍五入)
     string s_num9 = to_string(1.23456789e-5); // "0.000012"(科学计数法转为小数时可能会丢失精度)
     string s_num10 = to_string(1.23456789e5); // "123456.789000"(科学计数法转为小数时可能会丢失精度)
     string s_num11 = to_string(1.23456789e-10); // "0.000000"(科学计数法转为小数时可能会丢失精度)
     string s_num12 = to_string(1.23456789e10); // "12345678900.000000"(科学计数法转为小数时可能会丢失精度)
  • sum()(<numeric>):C++17 新增,直接计算容器元素之和

    vector<int> nums = {1,2,3,4};
    int sum = std::sum(nums); // 10
  • enumerate()(C++20 结构化绑定 + enumerate):同时获取元素索引和值

    vector<string> words = {"hello", "world"};
    for (auto& [index, word] : enumerate(words)) {
      cout << index << ": " << word << endl;
    }

数据结构

  • string(字符串)

    string s = "hello";
    s += " world"; // 拼接字符串
    cout << s.length(); // 获取长度
    cout << s.size();   // 获取长度(同 length())
    cout << s[0]; // 访问字符
    cout << s.substr(0, 5); // 截取子串 "hello",从索引0开始,长度为5
    cout << s.find("world"); // 查找子串,返回索引
    cout << s.empty(); // 判断是否为空
    cout << s.clear(); // 清空字符串
    cout << s.c_str(); // 获取 C 风格字符串(const char*)
    cout << s.begin(); // 获取迭代器
    cout << s.end();   // 获取迭代器
    string num_str = to_string(123); // 数字转字符串
    int num = stoi("456"); // 字符串转数字
    int num2 = atoi("789"); // C 风格字符串转数字
    int num3 = stoi("123abc"); // 字符串转数字,遇到非数字停止,结果为123
    int num4 = stoi("abc123"); // 字符串转数字,开头非数字,抛出异常
    int num5 = stoi("2147483648"); // 字符串转数字,超出 int 范围,抛出异常
    int num6 = stoi("-2147483649"); // 字符串转数字,超出 int 范围,抛出异常
    int num7 = stoi("-123"); // 字符串转数字,负数,结果为-123
    int num8 = stoi("+123"); // 字符串转数字,正数,结果为123
    int num9 = stoi("   123"); // 字符串转数字,前面有空格,结果为123
    int num10 = stoi("123   "); // 字符串转数字,后面有空格,结果为123
    int num11 = stoi("   -123   "); // 字符串转数字,前后有空格,结果为-123
    int num12 = stoi("   +123   "); // 字符串转数字,前后有空格,结果为123
    string copy_s = s; // 复制字符串
    string move_s = std::move(s); // 移动字符串(s 变为空)
    string swap_s;
    swap(s, swap_s); // 交换字符串内容
    string sorted_s = s; // 复制字符串
    sort(sorted_s.begin(), sorted_s.end()); // 排序字符串
    string reversed_s = s; // 复制字符串
    reverse(reversed_s.begin(), reversed_s.end()); // 反转字符串
    string unique_s = s; // 复制字符串
    sort(unique_s.begin(), unique_s.end()); // 先排序
    unique_s.erase(unique(unique_s.begin(), unique_s.end()), unique_s.end()); // 去重
    for (char c : s) { // 遍历字符串
      cout << c << " ";
    }
    for (size_t i = 0; i < s.length(); i++) { // 通过索引访问字符
      cout << s[i] << " ";
    }
    for (auto it = s.begin(); it != s.end(); it++) { // 通过迭代器访问字符
    cout << *it << " ";
    }
    for (auto& c : s) { // 遍历字符串(引用避免复制)
    cout << c << " ";
    }
    for (auto& [index, c] : enumerate(s)) { // C++20 结构化绑定 + enumerate
    cout << index << ": " << c << endl;
    }
    string char2str(1, 'a'); // char 转 string
    char c = s[0]; // string 转 char
  • vector(动态数组)

    vector<int> vec;
    vec.push_back(1); // 尾部添加元素
    vec.pop_back();   // 尾部删除元素
    vec.size();       // 获取元素个数
    vec.empty();      // 判断是否为空
    vec.clear();      // 清空所有元素
    vec.resize(5);    // 调整大小为5(不足补默认值,超出截断)
    vec.begin();       // 获取迭代器
    vec.end();         // 获取迭代器
    vec[0];          // 访问元素(不检查越界)
    vec.at(0);       // 访问元素(检查越界,抛出异常)
    vec.insert(vec.begin() + 1, 10); // 在索引1位置插入10
    vec.erase(vec.begin() + 1); // 删除索引1位置的元素
    vec.clear(); // 清空所有元素
    vec.empty(); // 判断是否为空
    vec.emplace_back(2); // 直接构造元素(效率更高)
    vec.reserve(100); // 预留空间,避免频繁扩容
    vecotr<int> copy_vec(vec); // 复制 vector
    vector<int> assign_vec(5, 0); // 创建一个包含5个0的 vector
    vector<int> range_vec(vec.begin(), vec.begin() + 3); // 创建一个包含 vec 前3个元素的 vector
    vector<int> move_vec(std::move(vec)); // 移动 vector(vec 变为空)
    vector<int> swap_vec;
    swap(vec, swap_vec); // 交换两个 vector 的内容
    vector<int> sorted_vec = vec; // 复制 vector
    sort(sorted_vec.begin(), sorted_vec.end()); // 排序 vector
    vector<int> reversed_vec = vec; // 复制 vector
    reverse(reversed_vec.begin(), reversed_vec.end()); // 反转 vector
    vector<int> unique_vec = vec; // 复制 vector
    sort(unique_vec.begin(), unique_vec.end()); // 先排序
    unique_vec.erase(unique(unique_vec.begin(), unique_vec.end()), unique_vec.end()); // 去重
    for (int x : vec) { // 遍历 vector
      cout << x << " ";
    }
    for (size_t i = 0; i < vec.size(); i++) { // 通过索引访问元素
      cout << vec[i] << " ";
    }
    for (auto it = vec.begin(); it != vec.end(); it++) { // 通过迭代器访问元素
      cout << *it << " ";
    }
    for (auto& x : vec) { // 遍历 vector(引用避免复制)
      cout << x << " ";
    }
    for (auto& [index, value] : enumerate(vec)) { // C++20 结构化绑定 + enumerate
      cout << index << ": " << value << endl;
    }
    vector<int> vec2 = {1, 2, 3, 4}; // 列表初始化 vector
    vector<int> vec3{1, 2, 3, 4}; // 列表初始化 vector(C++11 语法)
    vector<int> vec4(5, 0); // 创建一个包含5个0的 vector
  • deque(双端队列),支持两端插入删除,比 vector 更灵活

    deque<int> dq;
    dq.push_back(1);               // 尾部添加
    dq.push_front(2);              // 前部添加
    dq.pop_back();                 // 尾部删除
    dq.pop_front();                // 前部删除
    dq.size();                     // 获取元素个数
    dq.empty();                    // 判断是否为空
    dq.clear();                    // 清空所有元素
    dq[0];                         // 访问元素(不检查越界)
    dq.at(0);                      // 访问元素(检查越界,抛出异常)
    dq.insert(dq.begin() + 1, 10); // 在索引1位置插入10
    dq.erase(dq.begin() + 1);      // 删除索引1位置的元素
    dq.emplace_front(3);           // 前部直接构造元素
    dq.emplace_back(4);            // 尾部直接构造元素
    deque<int> copy_dq(dq);        // 复制 deque
    deque<int> assign_dq(5, 0);    // 创建一个包含5个0的 deque
    deque<int> range_dq(dq.begin(),
                        dq.begin() + 3); // 创建一个包含 dq 前3个元素的 deque
    deque<int> move_dq(std::move(dq));   // 移动 deque(dq 变为空)
    deque<int> swap_dq;
    swap(dq, swap_dq);                               // 交换两个 deque 的内容
    deque<int> sorted_dq = dq;                       // 复制 deque
    sort(sorted_dq.begin(), sorted_dq.end());        // 排序 deque
    deque<int> reversed_dq = dq;                     // 复制 deque
    reverse(reversed_dq.begin(), reversed_dq.end()); // 反转 deque
    deque<int> unique_dq = dq;                       // 复制 deque
    sort(unique_dq.begin(), unique_dq.end());        // 先排序
    unique_dq.erase(unique(unique_dq.begin(), unique_dq.end()),
                    unique_dq.end()); // 去重
    for (int x : dq) {                // 遍历 deque
        cout << x << " ";
    }
    for (size_t i = 0; i < dq.size(); i++) { // 通过索引访问元素
        cout << dq[i] << " ";
    }
    for (auto it = dq.begin(); it != dq.end(); it++) { // 通过迭代器访问元素
        cout << *it << " ";
    }
    for (auto& x : dq) { // 遍历 deque(引用避免复制)
        cout << x << " ";
    }
    for (auto& [index, value] : enumerate(dq)) { // C++20 结构化绑定 + enumerate
        cout << index << ": " << value << endl;
    }
  • stack(栈),后进先出(LIFO)

    stack<int> st;
    st.push(1); // 入栈
    st.top();   // 获取栈顶元素
    st.pop();   // 出栈
    st.empty(); // 判断是否为空
    st.size();  // 获取元素个数
    st.emplace(2); // 直接构造元素(效率更高)
    stack<int> copy_st(st); // 复制 stack
    stack<int> move_st(std::move(st)); // 移动 stack(st 变为空)
    stack<int> swap_st;
    swap(st, swap_st); // 交换两个 stack 的内容
    for (stack<int> temp = st; !temp.empty(); temp.pop()) { // 遍历 stack(需要复制一份)
    	cout << temp.top() << " ";
    }
    while (!st.empty()) { // 通过循环访问栈顶元素
    	cout << st.top() << " ";	st.pop();
    }
  • queue(队列),先进先出(FIFO)

    queue<int> q;
    q.push(1); // 入队
    q.front(); // 获取队头元素
    q.pop();   // 出队
    q.empty(); // 判断是否为空
    q.size();  // 获取元素个数
    q.emplace(2); // 直接构造元素(效率更高)
    queue<int> copy_q(q); // 复制 queue
    queue<int> move_q(std::move(q)); // 移动 queue(q 变为空)
    queue<int> swap_q;
    swap(q, swap_q); // 交换两个 queue 的内容
    while (!q.empty()) { // 通过循环访问队头元素
    	cout << q.front() << " ";	q.pop();
    }
    queue<int> temp_q(q); // 复制一份 queue 用于遍历
    while (!temp_q.empty()) {
    	cout << temp_q.front() << " ";	temp_q.pop();
    }
  • priority_queue(优先队列 / 堆),默认大顶堆(堆顶是最大值),算法题中常用来实现贪心 / 堆排序

    // 大顶堆(默认)
    priority_queue<int> max_heap;
    max_heap.push(3);
    max_heap.push(1);
    max_heap.push(5);
    cout << max_heap.top(); // 输出5
    max_heap.pop(); // 弹出5
    max_heap.top(); // 输出3
    max_heap.empty(); // 判断是否为空
    max_heap.size(); // 获取元素个数
    max_heap.emplace(2); // 直接构造元素(效率更高)
    priority_queue<int> copy_heap(max_heap); // 复制 priority_queue
    priority_queue<int> move_heap(std::move(max_heap)); // 移动 priority_queue(max_heap 变为空)
    priority_queue<int> swap_heap;
    swap(max_heap, swap_heap); // 交换两个 priority_queue 的内容
    for (priority_queue<int> temp = max_heap; !temp.empty(); temp.pop()) { // 遍历 priority_queue(需要复制一份)
      cout << temp.top() << " ";
    }
    vector<int> vec = {4, 2, 7, 1};
    priority_queue<int> max_heap2(vec.begin(), vec.end()); // 直接用 vector 初始化大顶堆
    priority_queue<int, vector<int>, greater<int>> min_heap(vec.begin(), vec.end()); // 直接用 vector 初始化小顶堆
    
    // 小顶堆(自定义)
    priority_queue<int, vector<int>, greater<int>> min_heap;
    min_heap.push(3);
    min_heap.push(1);
    min_heap.push(5);
    cout << min_heap.top(); // 输出1
  • unordered_map(哈希表),常用于统计元素频率(比 map 效率高,无排序)

    unordered_map<int, int> freq;
    freq[1]++; // 统计1出现的次数
    freq[2] = 3;
    // 遍历哈希表
    for (auto& pair : freq) {
        cout << pair.first << ": " << pair.second << endl;
    }
    // 查找元素
    if (freq.count(1)) {
      cout << "1出现了" << freq[1] << "次" << endl;
    }
    // 删除元素
    freq.erase(1);
    // 清空哈希表
    freq.clear();
    // 复制 unordered_map
    unordered_map<int, int> copy_freq(freq);
    // 移动 unordered_map
    unordered_map<int, int> move_freq(std::move(freq)); // freq 变为空
    // 交换 unordered_map
    unordered_map<int, int> swap_freq;
    swap(freq, swap_freq); // 交换两个 unordered_map 的内容
    // 获取哈希表大小
    cout << "哈希表大小:" << freq.size() << endl;
    // 判断哈希表是否为空
    cout << "哈希表是否为空:" << freq.empty() << endl;
    // 获取哈希表中某个键的值(如果键不存在会自动创建并初始化为0)
    cout << "键2的值:" << freq[2] << endl;
    // 获取哈希表中某个键的值(如果键不存在不会创建,返回默认值0)
    cout << "键3的值:" << freq.at(3) << endl;
    // 从 vector 初始化 unordered_map(统计频率)
    vector<int> nums = {1,2,2,3,3,3};
    unordered_map<int, int> freq2;
    for (int x : nums) {
      freq2[x]++;
    }
    // 直接用 vector 初始化 unordered_map(不统计频率,只是把元素作为键,值默认0)
    unordered_map<int, int> freq3(nums.begin(), nums.end());
    // 查找元素是否存在
    if(freq2.find(2) != freq2.end()) {
      cout << "2存在,出现了" << freq2[2] << "次" << endl;
    }
    if(freq2.find(4) == freq2.end()) {
      cout << "4不存在" << endl;
    }
  • unordered_set(哈希集合),常用于去重 / 查找存在性(比 set 效率高,无排序)

    unordered_set<int> s;
    s.insert(1); // 插入元素
    s.erase(1); // 删除元素
    s.count(1); // 判断元素是否存在
    s.empty(); // 判断是否为空
    s.size(); // 获取元素个数
    for (int x : s) { // 遍历 unordered_set
      cout << x << " ";
    }
    unordered_set<int> copy_s(s); // 复制 unordered_set
    unordered_set<int> move_s(std::move(s)); // 移动 unordered_set(s 变为空)
    unordered_set<int> swap_s;
    swap(s, swap_s); // 交换两个 unordered_set 的内容
    // 查找元素是否存在
    if(s2.find(2) != s2.end()) {
      cout << "2存在" << endl;
    }
    if(s2.find(4) == s2.end()) {
      cout << "4不存在" << endl;
    }
    // 从 vector 初始化 unordered_set(去重)
    vector<int> nums = {1,2,2,3,3,3};
    unordered_set<int> s3(nums.begin(), nums.end());
  • set(有序集合),常用于去重 / 查找存在性(比 unordered_set 效率低,有排序)

    set<int> s;
    s.insert(1);      // 插入元素
    s.erase(1);       // 删除元素
    s.count(1);       // 判断元素是否存在
    s.empty();        // 判断是否为空
    s.size();         // 获取元素个数
    for (int x : s) { // 遍历 set(有序)
        cout << x << " ";
    }
    set<int> copy_s(s);            // 复制 set
    set<int> move_s(std::move(s)); // 移动 set(s
    set<int> swap_s;
    swap(s, swap_s); // 交换两个 set 的内容
    // 查找元素是否存在
    if (s2.find(2) != s2.end()) {
        cout << "2存在" << endl;
    }
    if (s2.find(4) == s2.end()) {
        cout << "4不存在" << endl;
    }
    // 从 vector 初始化 set(去重)
    vector<int> nums = {1, 2, 2, 3, 3, 3};
    set<int> s3(nums.begin(), nums.end());
  • pair(键值对),常用于 map / unordered_map 的元素类型,也可单独使用

    pair<int, string> p(1, "one"); // 创建一个 pair
    cout << p.first; // 访问第一个元素
    cout << p.second; // 访问第二个元素
    pair<int, string> copy_p(p); // 复制 pair
    pair<int, string> move_p(std::move(p)); // 移动 pair(p 变为空)
    pair<int, string> swap_p;
    swap(p, swap_p); // 交换两个 pair 的内容
    make_pair(2, "two"); // 创建一个 pair(类型自动推断)
    pair<int, string> p2 = make_pair(3, "three"); // 创建
    pair<int, string> p3 = {4, "four"}; // 列表初始化创建 pair
    vector<pair<int, string>> vec = {{1, "one"}, {2, "two"}}; // vector 中的 pair
    for (const auto& [num, word] : vec) { // C++17 结构化绑定遍历 vector 中的 pair
    cout << num << ": " << word << endl;
    }
    vec.emplace_back(3, "three"); // 直接构造一个 pair 插入 vector
    vec.emplace_back(make_pair(4, "four")); // 直接构造一个 pair 插入 vector(使用 make_pair)
    vec.emplace_back({5, "five"}); // 直接构造一个 pair 插入 vector(使用列表初始化)
  • tuple(元组),可包含多个不同类型的元素,常用于函数返回多个值

    tuple<int, string, double> t(1, "one", 3.14); // 创建一个 tuple
    cout << get<0>(t); // 访问第一个元素
    cout << get<1>(t); // 访问第二个元素
    cout << get<2>(t); // 访问第三个元素
    tuple<int, string, double> copy_t(t); // 复制 tuple
    tuple<int, string, double> move_t(std::move(t)); // 移动 tuple(t 变为空)
    tuple<int, string, double> swap_t;
    swap(t, swap_t); // 交换两个 tuple 的内容
    make_tuple(2, "two", 2.71); // 创建一个 tuple(类型自动推断)
    auto t2 = make_tuple(3, "three", 1.61); // 创建一个 tuple(类型自动推断)
    auto [num, word, pi] = t2; // C++17 结构化绑定解包 tuple

高级用法

  • lambda 表达式:匿名函数,常用于算法中的自定义比较器 / 条件

    vector<int> nums = {1,2,3,4,5};
    sort(nums.begin(), nums.end(), [](int a, int b) {
      return a > b; // 降序排序
    });
    int count_even = count_if(nums.begin(), nums.end(), [](int x) {
      return x % 2 == 0; // 统计偶数的个数
    });
    auto longest_it = max_element(words.begin(), words.end(), [](const string& a, const string& b) {
      return a.length() < b.length(); // 获取最长字符串
    });
  • 函数内匿名函数:在函数内部定义一个匿名函数,常用于递归 / 回调

    void recursive_function(int n) {
      if (n <= 0) return;
      cout << n << " ";
      auto next = [](int x) { return x - 1; }; // 定义一个匿名函数
      recursive_function(next(n)); // 递归调用匿名函数
    }
    // 捕获外部变量的匿名函数
    void capture_example() {
      int count = 0;
      auto addCount = [count](int x) { count += x; }; // 定义一个捕获外部变量的匿名函数(值捕获,count 的值被复制到匿名函数中)
      addCount(5); // 调用匿名函数,count 仍然是0,因为匿名函数内部的 count 是一个副本
      cout << "Count: " << count << endl; // 输出 Count: 0
      auto increment = [&count]() { count++; }; // 定义一个捕获外部变量的匿名函数
      increment(); // 调用匿名函数,count 变为1
      increment(); // 调用匿名函数,count 变为2
      cout << "Count: " << count << endl; // 输出 Count: 2
    }
    // 生命周期:捕获外部变量的匿名函数必须在被捕获变量的生命周期内使用,否则会导致未定义行为
    void invalid_capture() {
      auto invalid_func = [count]() { return count; }; // 定义一个捕获外部变量的匿名函数(值捕获)
      // count 变量在匿名函数定义时已经超出作用域,导致 invalid_func 捕获了一个无效的变量副本
      cout << "Invalid capture: " << invalid_func() << endl; // 行为未定义,可能输出垃圾值或崩溃
    }
  • 函数对象(仿函数):定义一个类,重载 operator(),使其成为一个可调用对象

    struct Add {
      int operator()(int a, int b) const {
    	  return a + b; // 定义一个函数对象,实现加法
      }
    };
    Add add; // 创建一个函数对象实例
    int result = add(3, 4); // 调用函数对象,结果为7
    // 函数对象也可以有成员变量
    struct Counter {
      int count = 0;
      void operator()() {
    	  count++; // 每次调用函数对象时,count 增加1
      }
    };
    Counter counter; // 创建一个函数对象实例
    counter(); // 调用函数对象,count 变为1
    counter(); // 调用函数对象,count 变为2
    cout << "Counter: " << counter.count << endl; // 输出 Counter: 2
    // 函数对象也可以有构造函数
    struct Multiplier {
      int factor;
      Multiplier(int f) : factor(f) {} // 构造函数,初始化 factor
      int operator()(int x) const {
    	  return x * factor; // 定义一个函数对象,实现乘法
      }
    };
    Multiplier times2(2); // 创建一个函数对象实例,factor 为2
    int result2 = times2(5); // 调用函数对象,结果为10
    // 局部类也可以作为函数对象使用
    void local_class_example() {
      class LocalAdder {
      public:
    	  int operator()(int a, int b) const {
    		  return a + b; // 定义一个局部类函数对象,实现加法
    	  }
      };
      LocalAdder adder; // 创建一个局部类函数对象实例
      int result = adder(3, 4); // 调用局部类函数对象,结果为7
    }
这篇文档有帮助吗?

On this page

页面信息