c++中如何使用std::minmax_element_c++同时获取最大最小值【详解】

std::minmax_element是一次遍历容器同时返回最小和最大元素迭代器的算法,时间复杂度约1.5×n,优于两次调用min/max_element;返回std::pair,需判空后解引用,要求双向迭代器。

st

d::minmax_element 是什么,为什么不用两次 std::min_element

它是一个标准库算法,一次性遍历容器,同时找出最小和最大元素的迭代器。相比分别调用 std::min_elementstd::max_element,它把两次遍历压缩成一次,时间复杂度从 2×n 降到 ~1.5×n(实际实现通常采用成对比较策略),对大容器有可测的性能收益。

注意:它返回的是 std::pair,第一个是 min 的迭代器,第二个是 max 的迭代器 —— 不是值,是位置。

基本用法与常见错误

最常出错的是忽略返回值类型、解引用前没判空、或误以为它返回值而非迭代器。

  • 必须确保容器非空,否则解引用返回的迭代器是未定义行为
  • std::minmax_element 要求迭代器支持双向遍历(std::vectorstd::list 可以;std::forward_list 不行)
  • 若容器只有一个元素,返回的 pair 中两个迭代器相等(min 和 max 是同一个位置)
std::vector v = {3, 1, 4, 1, 5};
if (!v.empty()) {
    auto result = std::minmax_element(v.begin(), v.end());
    int min_val = *result.first;
    int max_val = *result.second;
    // min_val == 1, max_val == 5
}

自定义比较逻辑怎么写

和大多数 STL 算法一样,第三个参数是可选的二元谓词(函数对象)。它决定“谁更小”,和 std::sort 的 comp 语义一致:若 comp(a, b) == true,则 a 排在 b 前面(即 a “小于” b)。

  • 想按绝对值找极值?传 [](int a, int b) { return std::abs(a)
  • std::string 按长度比较?用 [](const std::string& a, const std::string& b) { return a.size()
  • 注意:这个谓词同时用于 min 和 max 判定,所以它必须定义一个**全序关系**(满足自反、反对称、传递)
std::vector words = {"a", "bb", "ccc", "dd"};
auto iters = std::minmax_element(words.begin(), words.end(),
    [](const std::string& x, const std::string& y) {
        return x.length() < y.length();
    });
// *iters.first == "a", *iters.second == "ccc"

和 std::minmax 的关键区别

别把 std::minmax_elementstd::minmax 搞混:std::minmax 只接受两个值(或 initializer_list),返回 pair of values;而 std::minmax_element 接受迭代器范围,返回 pair of iterators —— 它们解决的是完全不同的问题。

  • 你有一堆数要扫一遍找极值位置 → 用 std::minmax_element
  • 你只有两个变量 a 和 b,想快速得到 {min(a,b), max(a,b)} → 用 std::minmax(a, b)
  • 你有一个 std::initializer_list{1,5,3},想直接得极值 → 用 std::minmax({1,5,3})(但注意它不支持自定义比较器的 initializer_list 版本)

真正容易被忽略的是:当容器为空时,std::minmax_element 返回 {last, last},此时 result.first == result.second == v.end() —— 必须检查,不能直接解引用。