侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论
STL

使用 vector 删除特定条件的元素

2025-12-12 / 0 评论 / 4 阅读

题目

使用 vector 删除特定条件的元素

信息

  • 类型:问答
  • 难度:⭐

考点

vector 基本操作, 迭代器失效问题, 删除元素的标准方法

快速回答

正确删除 vector 中元素的标准方法是使用 Erase-Remove 惯用法

  1. 使用 std::remove_if 算法将需要保留的元素移动到容器前部
  2. 配合 vector::erase 删除尾部多余元素

错误做法是直接使用迭代器循环删除,这会导致迭代器失效:

// 错误示例(迭代器失效)
for(auto it = vec.begin(); it != vec.end(); ++it) {
    if(*it % 2 == 0) {
        vec.erase(it);  // 此处 it 失效
    }
}
## 解析

问题场景

给定一个整数 vector,要求删除其中所有偶数元素。例如:输入 {1, 2, 3, 4, 5},输出 {1, 3, 5}

原理说明

在 vector 中删除元素时需注意两个关键点:

  • 迭代器失效:调用 erase() 后,被删除元素及其后的所有迭代器都会失效
  • 高效操作:vector 尾部插入/删除高效,但中间删除会导致元素移动

正确解决方案

使用 Erase-Remove 惯用法(C++11 起):

#include <algorithm>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 1. 使用 remove_if 将偶数移到末尾
    auto new_end = std::remove_if(vec.begin(), vec.end(), 
        [](int n) { return n % 2 == 0; });

    // 2. 删除末尾的无效元素
    vec.erase(new_end, vec.end());

    // 结果:vec = {1, 3, 5}
}

最佳实践

  • C++20 优化:使用 std::erase_if 更简洁
    std::erase_if(vec, [](int n) { return n % 2 == 0; });
  • Lambda 表达式:灵活定义删除条件
  • 性能考量:时间复杂度 O(n),只需一次元素遍历

常见错误

  • 迭代器失效陷阱:在循环中直接使用 erase() 后继续使用原迭代器
  • 错误修正尝试:以下写法仍存在缺陷
    // 危险!可能遗漏连续偶数
    for(auto it = vec.begin(); it != vec.end(); ) {
        if(*it % 2 == 0) {
            it = vec.erase(it); // 正确获取返回值但效率低
        } else {
            ++it;
        }
    }
  • 无效索引法:从后向前遍历索引仍会导致多次数据移动

扩展知识

  • 其他容器差异
    • list 可直接使用 remove_if 成员函数(效率更高)
    • map/set 在循环中使用 erase(it++) 是安全的
  • 算法原理remove_if 通过双指针实现:
    1. 第一个指针遍历所有元素
    2. 第二个指针指向下一个保留位置
    3. 最终返回保留区的结束迭代器
  • 性能对比:Erase-Remove 比循环删除快 5-10 倍(避免重复移动元素)