目 录CONTENT

文章目录

C++ STL:算法-非变动算法

TalentQ
2025-08-28 / 0 评论 / 0 点赞 / 5 阅读 / 0 字

什么是非变动算法?

非变动算法(Non-modifying Sequence Operations)是指不会直接修改容器元素值的算法。它们通常用于查找、计数、比较、遍历等操作,保证原始数据不被更改,适合读操作场景。

常见非变动算法包括:

  • for_each

  • find

  • find_if

  • find_if_not

  • count

  • count_if

  • all_of

  • any_of

  • none_of

  • mismatch

  • equal

  • search

  • adjacent_find

2 非变动算法详解

2.1 for_each

原理:
对区间内每个元素执行指定操作(通常是函数或 Lambda),不会修改元素值。

用法:

#include <algorithm>
#include <vector>
#include <iostream>

void PrintElement(int x) {
  std::cout << x << " ";
}

int main() {
  std::vector<int> vec = {1, 2, 3, 4, 5};
  // 对每个元素执行 PrintElement
  std::for_each(vec.begin(), vec.end(), PrintElement);
  std::cout << std::endl;
  return 0;
}

适用场景:
遍历容器并执行只读操作(如打印、统计)。

对比传统方法:
传统 for 循环也能实现,但 for_each 更简洁、可读性更强,且可结合函数对象或 Lambda 使用。

2.2 find

原理:
在区间内查找第一个等于指定值的元素,返回迭代器。

用法:

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
  std::vector<int> vec = {10, 20, 30, 40};
  auto it = std::find(vec.begin(), vec.end(), 30);
  if (it != vec.end()) {
    std::cout << "Found: " << *it << std::endl;
  } else {
    std::cout << "Not found" << std::endl;
  }
  return 0;
}

适用场景:
查找具体值是否存在。

对比传统方法:
手写 for 循环查找,代码冗长且易出错;find 简化实现。

2.3 find_iffind_if_not

原理:

  • find_if:查找第一个满足谓词条件的元素。

  • find_if_not:查找第一个不满足谓词条件的元素。

用法:

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
  std::vector<int> vec = {2, 4, 5, 8};
  // 查找第一个奇数
  auto it = std::find_if(vec.begin(), vec.end(), [](int x) { return x % 2 != 0; });
  if (it != vec.end()) {
    std::cout << "First odd: " << *it << std::endl;
  }
  // 查找第一个不是偶数的元素
  auto it2 = std::find_if_not(vec.begin(), vec.end(), [](int x) { return x % 2 == 0; });
  if (it2 != vec.end()) {
    std::cout << "First not even: " << *it2 << std::endl;
  }
  return 0;
}

适用场景:
查找满足自定义条件的元素。

对比传统方法:
传统 for 循环需手动写条件判断,find_if 更灵活且易维护。

2.4 countcount_if

原理:

  • count:统计区间内等于指定值的元素个数。

  • count_if:统计区间内满足谓词条件的元素个数。

用法:

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
  std::vector<int> vec = {1, 2, 2, 3, 4, 2};
  // 统计值为2的元素个数
  int cnt = std::count(vec.begin(), vec.end(), 2);
  std::cout << "Count of 2: " << cnt << std::endl;

  // 统计偶数个数
  int even_cnt = std::count_if(vec.begin(), vec.end(), [](int x) { return x % 2 == 0; });
  std::cout << "Count of even: " << even_cnt << std::endl;
  return 0;
}

适用场景:
统计元素出现次数、满足条件的元素数量。

对比传统方法:
手动累加计数,count/count_if更高效、代码更简洁。

2.5 all_ofany_ofnone_of

原理:

  • all_of:区间内所有元素都满足谓词条件。

  • any_of:区间内有任意一个元素满足谓词条件。

  • none_of:区间内没有元素满足谓词条件。

用法:

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
  std::vector<int> vec = {2, 4, 6, 8};
  bool all_even = std::all_of(vec.begin(), vec.end(), [](int x) { return x % 2 == 0; });
  bool any_odd = std::any_of(vec.begin(), vec.end(), [](int x) { return x % 2 != 0; });
  bool none_negative = std::none_of(vec.begin(), vec.end(), [](int x) { return x < 0; });

  std::cout << "All even: " << all_even << std::endl;
  std::cout << "Any odd: " << any_odd << std::endl;
  std::cout << "None negative: " << none_negative << std::endl;
  return 0;
}

适用场景:
快速判断一组元素是否全部/部分/完全不满足某条件。

对比传统方法:
传统 for 循环需手动设置标志变量,易出错;STL算法高效且表达力强。

2.6 mismatch

原理:
比较两个区间,返回第一个不相等的元素对的迭代器。

用法:

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
  std::vector<int> a = {1, 2, 3, 4};
  std::vector<int> b = {1, 2, 0, 4};
  auto result = std::mismatch(a.begin(), a.end(), b.begin());
  if (result.first != a.end()) {
    std::cout << "First mismatch: " << *result.first << " vs " << *result.second << std::endl;
  } else {
    std::cout << "No mismatch found" << std::endl;
  }
  return 0;
}

适用场景:
比较两个序列,查找第一个不同的元素。

对比传统方法:
手写 for 循环比较,代码繁琐;mismatch一行代码解决。

2.7 equal

原理:
判断两个区间的元素是否全部相等。

用法:

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
  std::vector<int> a = {1, 2, 3};
  std::vector<int> b = {1, 2, 3};
  bool is_equal = std::equal(a.begin(), a.end(), b.begin());
  std::cout << "Is equal: " << is_equal << std::endl;
  return 0;
}

适用场景:
判断两个序列内容完全一致。

对比传统方法:
手动逐元素比较,equal更简洁高效。

原理:
在区间内查找另一个区间(子序列)首次出现的位置。

用法:

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
  std::vector<int> vec = {1, 2, 3, 4, 2, 3};
  std::vector<int> sub = {2, 3};
  auto it = std::search(vec.begin(), vec.end(), sub.begin(), sub.end());
  if (it != vec.end()) {
    std::cout << "Subsequence found at index: " << std::distance(vec.begin(), it) << std::endl;
  } else {
    std::cout << "Subsequence not found" << std::endl;
  }
  return 0;
}

适用场景:
查找子序列在容器中的位置。

对比传统方法:
传统嵌套循环查找子序列,代码复杂;search一行搞定。

2.9 adjacent_find

原理:
查找区间内相邻且满足条件的元素对,返回第一个元素的迭代器。

用法:

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
  std::vector<int> vec = {1, 2, 2, 3, 4};
  // 查找相邻相等的元素
  auto it = std::adjacent_find(vec.begin(), vec.end());
  if (it != vec.end()) {
    std::cout << "First adjacent equal: " << *it << std::endl;
  }
  return 0;
}

适用场景:
查找重复元素、特殊相邻关系。

对比传统方法:
手写 for 循环,易出错;adjacent_find更安全高效。

3 总结与扩展

3.1 优势

  • 代码简洁:STL算法将常用操作封装,大幅减少重复代码。

  • 安全高效:避免手动迭代错误,性能经过优化。

  • 表达力强:结合 Lambda 表达式,逻辑清晰易懂。

3.2 扩展应用

  • 可与变动算法结合,先用非变动算法筛选、统计,再用变动算法处理数据。

  • 结合自定义谓词,实现复杂条件判断和查找。

3.3 注意事项

  • 非变动算法不会改变容器内容,但 Lambda 或函数体内可间接修改外部数据,要注意副作用。

  • 使用正确的迭代器区间,避免越界。

0

评论区