笔记 C++11 std::minmax_element() 的使用(寻找最小值和最大值)

本文详细介绍了C++标准库中的minmax_element函数,该函数用于寻找容器中最小和最大元素的位置。通过示例展示了如何使用此函数,并对比了min_element和max_element的功能。

0. 函数的声明

  • 可以看到:返回一个 std::pair<ForwardIt,ForwardIt>pair 对)
template< class ForwardIt >
std::pair<ForwardIt,ForwardIt>
    minmax_element( ForwardIt first, ForwardIt last );

1. 寻找最小值和最大值

  • 使用
  • 顾名思义,从函数名看,minmax_element,先是 min,再 max,所以,返回的类中的数据成员 first 对应着最小值second 对应着最大值
  • 源码
template<class ForwardIt, class Compare>
std::pair<ForwardIt, ForwardIt> 
    minmax_element(ForwardIt first, ForwardIt last, Compare comp)
{
    auto min = first, max = first;
 
    if (first == last || ++first == last)
        return {min, max};
 
    if (comp(*first, *min)) {
        min = first;
    } else {
        max = first;
    }
 
    while (++first != last) {
        auto i = first;
        if (++first == last) {
            if (comp(*i, *min)) min = i;
            else if (!(comp(*i, *max))) max = i;
            break;
        } else {
            if (comp(*first, *i)) {
                if (comp(*first, *min)) min = first;
                if (!(comp(*i, *max))) max = i;
            } else {
                if (comp(*i, *min)) min = i;
                if (!(comp(*first, *max))) max = first;
            }
        }
    }
    return {min, max};
}
  • 例子:
#include <iostream>

int main() {
    
    std::vector<int> v = { 1, 2, 5, 4, 100, 0, -199, 33 };

    auto result = std::minmax_element(v.begin(), v.end());
    // 输出首次出现的最小元素
    std::cout << "min element is: " << *result.first << '\n';

    // 输出首次出现的最大元素
    std::cout << "max element is: " << *result.second << '\n';

    return 0;
}


/*
// 官网例子
#include <algorithm>
#include <iostream>

int main() {
    
    const auto v = { 3, 9, 1, 4, 2, 5, 9 };
    auto pStart = begin(v);
    auto pEnd = end(v);
    const auto result = std::minmax_element(begin(v), end(v));

    std::cout << "min = " << *result.first << ", max = " << *result.second << '\n';

    return 0;
}
*/

  • 结果:
    在这里插入图片描述

2. 其它类似的函数

1. C++17 中的 min_element, 返回迭代器位置, 复杂度为 O(n)

  • 源码
template<class ForwardIt>
ForwardIt min_element(ForwardIt first, ForwardIt last)
{
    if (first == last) return last;
 
    ForwardIt smallest = first;
    ++first;
    for (; first != last; ++first) {
        if (*first < *smallest) {
            smallest = first;
        }
    }
    return smallest;
}
  • 例子
#include <algorithm>
#include <iostream>
#include <vector>
 
int main()
{
    std::vector<int> v{3, 1, 4, 1, 5, 9};
 
    std::vector<int>::iterator result = std::min_element(v.begin(), v.end());
    std::cout << "min element at: " << std::distance(v.begin(), result) << std::endl;
    std::cout << "min value is: " << *result << std::endl;				// 1

	return 0;
}

2. C++17 中的 max_element, 返回迭代器位置, 复杂度为 O(n)

  • 源码
template<class ForwardIt>
ForwardIt max_element(ForwardIt first, ForwardIt last)
{
    if (first == last) return last;
 
    ForwardIt largest = first;
    ++first;
    for (; first != last; ++first) {
        if (*largest < *first) {
            largest = first;
        }
    }
    return largest;
}
  • 例子
#include <algorithm>
#include <iostream>
#include <vector>
 
int main()
{
    std::vector<int> v{3, 1, 4, 1, 5, 9};
 
    std::vector<int>::iterator result = std::max_element(v.begin(), v.end());
    std::cout << "max element at: " << std::distance(v.begin(), result) << std::endl;
    std::cout << "max value is: " << *result << std::endl;					// 9

	return 0;
}

3. 参考

https://en.cppreference.com/w/cpp/algorithm

<think>我们正在解决如何查找数组中的最小值。根据用户需求,我们需要参考站内引用,并尽可能多的参考用户上一次的问题回答。 从引用中我们可以看到多种方法,包括基础循环法使用函数封装的方法。同时,用户之前的问题是关于最大值的查找,现在需要查找最小值,方法类似。 方法总结: 1. 基础循环法:初始化min为数组第一个元素,然后遍历数组,如果遇到比当前min小的元素,则更新min。 2. 使用函数封装:可以定义一个函数,专门用于查找最小值,提高代码复用性。 3. 注意初始化问题:避免将min初始化为0,因为数组可能全为正数,这样会导致错误(但最小值0可能被忽略,所以更安全的做法是初始化为数组第一个元素)。 参考引用: 引用[2][4]提供了查找最小值的示例代码。 我们将提供两种方法: 方法一:基础循环法(主函数内实现) 方法二:使用函数封装(定义一个findMin函数) 同时,我们也会提到使用标准库的方法(虽然引用中没有直接提到,但我们可以补充,因为用户之前的问题提到了标准库函数max_element,同理有min_element)。 步骤: 1. 初始化最小值变量(通常为数组第一个元素)。 2. 遍历数组,逐个比较更新最小值。 3. 输出或返回最小值。 注意:数组长度计算(使用sizeof除法)或传递数组长度参数。 下面我们分别给出示例代码:</think>### C++ 数组中查找最小值的方法 在 C++ 中查找数组最小值与查找最大值原理相同,主要通过遍历比较实现。以下是三种可靠方法,均基于您提供的引用内容: #### 方法一:基础循环法(推荐) **核心步骤**: 1. 初始化 `min` 为数组第一个元素(避免负数问题) 2. 遍历数组,比较当前元素与 `min` 3. 若当前元素更小,则更新 `min` ```cpp #include <iostream> using namespace std; int main() { float arr[] = {57.58, 78.47, 48, 56.254, 55.24}; // 示例数组[^2] int size = sizeof(arr) / sizeof(arr[0]); // 计算数组长度 float min = arr[0]; // 关键:初始化为第一个元素 for(int i = 1; i < size; i++) { if(arr[i] < min) { // 比较当前元素与最小值 min = arr[i]; // 更新最小值 } } cout << "数组最小值: " << min << endl; // 输出:48 return 0; } ``` > **关键点**:初始化 `min=arr[0]` 确保正确处理负数数组[^2][^5] #### 方法二:函数封装法(提高复用性) **适用场景**:需多次查找不同数组的最小值 ```cpp #include <iostream> using namespace std; // 查找最小值的函数[^4] float findMin(float arr[], int size) { float min = arr[0]; for(int i = 1; i < size; i++) { if(arr[i] < min) min = arr[i]; } return min; } int main() { float arr1[] = {12.3, 4.5, 9.1, 7.8}; float arr2[] = {34, 22, 18, 42}; cout << "arr1最小值: " << findMin(arr1, 4) << endl; // 4.5 cout << "arr2最小值: " << findMin(arr2, 4) << endl; // 18 return 0; } ``` #### 方法三:标准库函数法(最简洁) 使用 `<algorithm>` 中的 `std::min_element`: ```cpp #include <iostream> #include <algorithm> // 包含min_element using namespace std; int main() { int arr[] = {3, 5, 1, 7}; // 引用[3]示例 int size = sizeof(arr)/sizeof(arr[0]); auto min_ptr = min_element(arr, arr + size); // 返回最小元素的指针 cout << "最小值: " << *min_ptr << endl; // 1 return 0; } ``` ### 关键注意事项 1. **初始化陷阱** 绝对不要初始化 `min=0`,若数组全为正数将得到错误结果[^5]。安全做法: ```cpp // 安全初始化方案 int min = arr[0]; // 方案1:首元素 int min = INT_MAX; // 方案2:<climits>中的最大值 ``` 2. **同时查找最大最小值** 只需单次遍历即可同步获取(引用[2][5]): ```cpp int max = arr[0], min = arr[0]; for(int i=1; i<size; i++) { if(arr[i] > max) max = arr[i]; if(arr[i] < min) min = arr[i]; // 注意用else if会出错 } ``` 3. **空数组处理** 增加安全检查: ```cpp if(size == 0) { cerr << "错误:空数组!"; return -1; // 或抛出异常 } ``` ### 性能分析 - **时间复杂度**:所有方法均为 $O(n)$,需完整遍历数组 - **空间复杂度**:$O(1)$,仅需常数级额外空间 - **优化建议**:超过 10⁶ 元素时,可考虑并行算法(OpenMP) > 实际项目中推荐 `std::min_element`,其经过编译器优化且代码简洁[^3]。若需兼容C语言或特殊场景,建议使用方法二封装函数。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值