首页 > 后端开发 > C++ > 正文

C++STL算法min_element和max_element使用

P粉602998670
发布: 2025-09-13 10:50:01
原创
920人浏览过
<blockquote>min_element和max_element是C++ STL中用于查找序列最小最大元素的算法,定义于头文件,接受迭代器范围并返回指向极值元素的迭代器,若序列为空则返回last迭代器;它们支持自定义比较谓词,常用于数据分析、游戏开发等场景,时间复杂度为O(N),使用时需注意空范围检查、重复元素返回首个位置及比较器的严格弱序要求。</blockquote> <p><img src="https://img.php.cn/upload/article/000/969/633/175773180276248.png" alt="c++stl算法min_element和max_element使用"></p> <p>C++ STL中的 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div> 和 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div> 算法是寻找给定序列中最小或最大元素的利器。它们接收一个范围(通过一对迭代器指定),并返回指向该范围内最小或最大元素的迭代器。这极大地简化了我们手动遍历序列进行比较的繁琐工作,是处理数据集合时非常高效且常用的<a style="color:#f60; text-decoration:underline;" title="工具" href="https://www.php.cn/zt/16887.html" target="_blank">工具</a>。</p> <h3>解决方案</h3> <p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div> 和 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div> 算法定义在 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;"><algorithm></pre>
登录后复制
</div> 头文件中,它们的基本用法非常直观。它们都接受两个迭代器参数,分别表示序列的起始和结束(开区间 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">[first, last)</pre>
登录后复制
</div>)。如果你需要自定义比较逻辑,还可以提供一个额外的二元谓词(binary p<a style="color:#f60; text-decoration:underline;" title="red" href="https://www.php.cn/zt/122037.html" target="_blank">red</a>icate)。</p> <p><strong>基本语法:</strong></p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:cpp;toolbar:false;'>template <class ForwardIterator> ForwardIterator min_element(ForwardIterator first, ForwardIterator last); template <class ForwardIterator, class Compare> ForwardIterator min_element(ForwardIterator first, ForwardIterator last, Compare comp); template <class ForwardIterator> ForwardIterator max_element(ForwardIterator first, ForwardIterator last); template <class ForwardIterator, class Compare> ForwardIterator max_element(ForwardIterator first, ForwardIterator last, Compare comp);</pre>
登录后复制
</div><p>这两个函数都会返回一个迭代器,指向找到的最小或最大元素。如果序列为空,它们会返回 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">last</pre>
登录后复制
</div> 迭代器。这是一个重要的边界条件,在使用返回值之前通常需要检查。</p> <p><span>立即学习</span>“<a href="https://pan.quark.cn/s/6e7abc4abb9f" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">C++免费学习笔记(深入)</a>”;</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:cpp;toolbar:false;'>#include <iostream> #include <vector> #include <algorithm> // 包含 min_element 和 max_element int main() { std::vector<int> numbers = {3, 1, 4, 1, 5, 9, 2, 6}; // 寻找最小元素 auto min_it = std::min_element(numbers.begin(), numbers.end()); if (min_it != numbers.end()) { std::cout << "最小元素是: " << *min_it << std::endl; // 输出 1 } else { std::cout << "序列为空,没有最小元素。" << std::endl; } // 寻找最大元素 auto max_it = std::max_element(numbers.begin(), numbers.end()); if (max_it != numbers.end()) { std::cout << "最大元素是: " << *max_it << std::endl; // 输出 9 } else { std::cout << "序列为空,没有最大元素。" << std::endl; } // 对于空序列的测试 std::vector<int> empty_numbers; auto empty_min_it = std::min_element(empty_numbers.begin(), empty_numbers.end()); if (empty_min_it == empty_numbers.end()) { std::cout << "空序列测试通过:min_element 返回 end() 迭代器。" << std::endl; } return 0; }</pre>
登录后复制
</div><p>我个人觉得,这种直接返回迭代器的设计非常C++,它给了我们极大的灵活性,我们不仅能获取到元素的值,还能知道它在序列中的“位置”,这在某些需要进一步操作的场景下特别有用。</p> <h3><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div> 和 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div> 的基本用法是怎样的?</h3> <p>这两个算法的核心在于它们是基于迭代器工作的,这意味着它们可以应用于任何支持前向迭代器(ForwardIterator)的容器,比如 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">std::vector</pre>
登录后复制
</div>, <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">std::list</pre>
登录后复制
</div>, <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">std::array</pre>
登录后复制
</div> 甚至普通数组。它们会遍历整个指定范围,通过默认的 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;"><</pre>
登录后复制
</div> 运算符(对于 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div>)或 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">></pre>
登录后复制
</div> 运算符(对于 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div>)进行比较,从而找出极值。</p> <p>让我用一个更具体的例子来展示,我们不仅要找到值,还要知道它在原序列中的大概位置(索引)。虽然 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div> 和 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div> 不直接返回索引,但我们可以通过 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">std::distance</pre>
登录后复制
</div> 辅助获取。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:cpp;toolbar:false;'>#include <iostream> #include <vector> #include <algorithm> // for min_element, max_element #include <iterator> // for std::distance int main() { std::vector<double> temperatures = {25.5, 23.1, 28.0, 24.7, 26.2}; // 寻找最低温度 auto min_temp_it = std::min_element(temperatures.begin(), temperatures.end()); if (min_temp_it != temperatures.end()) { // 计算索引 size_t index = std::distance(temperatures.begin(), min_temp_it); std::cout << "最低温度是: " << *min_temp_it << " (位于索引 " << index << ")" << std::endl; } // 寻找最高温度 auto max_temp_it = std::max_element(temperatures.begin(), temperatures.end()); if (max_temp_it != temperatures.end()) { size_t index = std::distance(temperatures.begin(), max_temp_it); std::cout << "最高温度是: " << *max_temp_it << " (位于索引 " << index << ")" << std::endl; } // 考虑有重复最小/最大值的情况 std::vector<int> scores = {85, 92, 78, 92, 88}; auto first_max_score_it = std::max_element(scores.begin(), scores.end()); if (first_max_score_it != scores.end()) { size_t index = std::distance(scores.begin(), first_max_score_it); std::cout << "第一次出现的最高分是: " << *first_max_score_it << " (位于索引 " << index << ")" << std::endl; // 注意:如果存在多个相同的最大值,它会返回指向第一个的迭代器。 // 在这个例子中,它会指向索引1的92,而不是索引3的92。 } return 0; }</pre>
登录后复制
</div><p>这里有个小细节,如果序列中有多个相同的最小或最大元素,<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div> 和 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div> 总是返回指向第一个遇到的那个元素的迭代器。这在某些场景下需要特别注意,比如你可能需要所有极值的位置,那这两个算法就不足以直接满足了,可能需要额外的遍历或组合其他算法。</p> <div class="aritcle_card"> <a class="aritcle_card_img" href="/xiazai/gongju/1553"> <img src="https://img.php.cn/upload/manual/000/000/008/169172680350318.png" alt="OpenCV"> </a> <div class="aritcle_card_info"> <a href="/xiazai/gongju/1553">OpenCV</a> <p>开源计算机视觉库拥有超过2500个算法,提供详细的文档和实时计算机视觉的示例代码。它可以在Windows、Linux、Mac OS X、Android、iOS上运行,并通过JavaScript在您的浏览器中使用。语言:C++、Python、Julia、Javascript主页:https://opencv.org问答论坛:https://forum.opencv.org/文档:https://docs.opencv.org源代码:https://github.com/opencv请特别关注我们的教程!ht</p> <div class=""> <img src="/static/images/card_xiazai.png" alt="OpenCV"> <span>20</span> </div> </div> <a href="/xiazai/gongju/1553" class="aritcle_card_btn"> <span>查看详情</span> <img src="/static/images/cardxiayige-3.png" alt="OpenCV"> </a> </div> <h3>如何为自定义类型或特定排序规则使用 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div> 和 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div>?</h3> <p>当处理自定义数据类型,或者需要非默认的比较逻辑时,<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div> 和 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div> 的重载版本就派上用场了。它们允许你传入一个二元谓词(binary predicate),也就是一个接受两个参数并返回 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">bool</pre>
登录后复制
</div> 值的函数对象、函数指针或 Lambda 表达式。这个谓词定义了“小于”或“大于”的含义。</p> <p>假设我们有一个表示学生信息的结构体,我们想根据学生的年龄或分数来查找最小或最大的学生。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:cpp;toolbar:false;'>#include <iostream> #include <vector> #include <algorithm> // for min_element, max_element #include <string> struct Student { std::string name; int age; double score; // 为了默认比较,我们可以重载 < 运算符,但通常我们更倾向于传入自定义谓词 // bool operator<(const Student& other) const { // return age < other.age; // 默认按年龄比较 // } }; // 辅助函数,用于打印学生信息 void print_student(const std::string& prefix, const Student& s) { std::cout << prefix << ": " << s.name << ", Age: " << s.age << ", Score: " << s.score << std::endl; } int main() { std::vector<Student> students = { {"Alice", 20, 95.5}, {"Bob", 22, 88.0}, {"Charlie", 19, 98.2}, {"David", 20, 91.0} }; // 1. 根据年龄寻找最小(最年轻)的学生 // 使用 Lambda 表达式作为比较器 auto youngest_student_it = std::min_element(students.begin(), students.end(), [](const Student& a, const Student& b) { return a.age < b.age; }); if (youngest_student_it != students.end()) { print_student("最年轻的学生", *youngest_student_it); // 预期 Charlie } // 2. 根据分数寻找最大(最高分)的学生 // 同样使用 Lambda 表达式 auto highest_score_student_it = std::max_element(students.begin(), students.end(), [](const Student& a, const Student& b) { return a.score < b.score; // 注意这里仍是 <,因为 max_element 寻找“最大” }); if (highest_score_student_it != students.end()) { print_student("最高分的学生", *highest_score_student_it); // 预期 Charlie } // 3. 寻找年龄最大的学生 (使用 min_element 结合 std::greater) // 看起来有点反直觉,但 std::greater<T>() 实际上定义了“大于”操作, // 当与 min_element 结合时,它会找到在“大于”意义上最小的元素,也就是实际意义上的最大元素。 // 不过,我个人更推荐直接用 max_element 和清晰的 lambda,避免这种思维上的弯路。 auto oldest_student_it = std::min_element(students.begin(), students.end(), [](const Student& a, const Student& b) { return a.age > b.age; // 寻找年龄“最小”的,但比较是 a.age > b.age }); if (oldest_student_it != students.end()) { print_student("年龄最大的学生", *oldest_student_it); // 预期 Bob } return 0; }</pre>
登录后复制
</div><p>这里需要强调的是,你提供的比较器必须满足严格弱序(Strict Weak Ordering)的要求。这意味着它必须是:</p> <ol> <li> <strong>非自反的</strong>:<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">comp(a, a)</pre>
登录后复制
</div> 必须为 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">false</pre>
登录后复制
</div>。</li> <li> <strong>非对称的</strong>:如果 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">comp(a, b)</pre>
登录后复制
</div> 为 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">true</pre>
登录后复制
</div>,那么 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">comp(b, a)</pre>
登录后复制
</div> 必须为 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">false</pre>
登录后复制
</div>。</li> <li> <strong>传递性的</strong>:如果 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">comp(a, b)</pre>
登录后复制
</div> 为 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">true</pre>
登录后复制
</div> 且 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">comp(b, c)</pre>
登录后复制
</div> 为 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">true</pre>
登录后复制
</div>,那么 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">comp(a, c)</pre>
登录后复制
</div> 也必须为 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">true</pre>
登录后复制
</div>。</li> <li> <strong>等价关系</strong>:如果 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">comp(a, b)</pre>
登录后复制
</div> 为 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">false</pre>
登录后复制
</div> 且 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">comp(b, a)</pre>
登录后复制
</div> 为 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">false</pre>
登录后复制
</div>,则 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">a</pre>
登录后复制
</div> 和 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">b</pre>
登录后复制
</div> 被认为是等价的。</li> </ol> <p>大多数时候,我们用 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">a < b</pre>
登录后复制
</div> 这样的 Lambda 表达式就能自然地满足这些要求,但如果你在写更复杂的自定义比较逻辑时,务必牢记这些原则,否则可能会导致未定义行为或非预期的结果。</p> <h3><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div> 和 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div> 在实际项目中有哪些常见应用场景和注意事项?</h3> <p>在实际开发中,<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div> 和 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div> 的应用场景非常广泛,几乎只要涉及到在数据集合中寻找极值,它们就能派上用场。</p> <p><strong>常见应用场景:</strong></p> <ol> <li> <strong>数据分析与统计:</strong> 快速找出数据集中的最大值、最小值,例如传感器读数中的最高温度、股票价格的最低点、用户评分的最高分等。这对于初步的数据探索和异常值检测非常有用。</li> <li> <strong><a style="color:#f60; text-decoration:underline;" title="游戏开发" href="https://www.php.cn/zt/24672.html" target="_blank">游戏开发</a>:</strong> 确定哪个玩家得分最高、哪个敌人血量最少、哪个道具价值最大等。</li> <li> <strong>资源调度与优化:</strong> 在多个服务器中寻找负载最低的那个进行任务分配,或者在多个可用资源中选择消耗最小的那个。</li> <li> <strong>图形图像处理:</strong> 查找图像中像素亮度最高的点或最低的点,这可能是图像增强或特征提取的第一步。</li> <li> <strong>算法实现:</strong> 作为其他更复杂算法的构建块,例如在某些贪心算法中,可能需要反复找出当前状态下的最优(最小或最大)选择。</li> <li> <strong>配置管理:</strong> 从一系列配置选项中,找出满足特定条件的最佳(或最差)配置。</li> </ol> <p><strong>注意事项:</strong></p> <ol> <li> <strong>时间复杂度:</strong> 这两个算法的时间复杂度都是线性的,即 O(N),其中 N 是序列中的元素数量。这意味着它们对于大多数规模的数据集都非常高效。不过,如果你的数据量极其庞大,并且需要频繁地查询极值,那么专门的数据结构(如最小/最大堆)可能会提供更好的性能,因为它们可以在对数时间内完成查询,但构建堆本身也需要 O(N) 的时间。</li> <li> <strong>空范围处理:</strong> 如前所述,如果传入的范围为空(<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">first == last</pre>
登录后复制
</div>),算法会返回 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">last</pre>
登录后复制
</div> 迭代器。因此,在使用返回的迭代器之前,务必进行空检查,避免解引用无效迭代器导致程序崩溃。</li> <li> <strong>重复元素:</strong> 当序列中存在多个与最小/最大值相等的元素时,<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div> 和 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div> 总是返回指向这些元素中“第一个”出现的迭代器。如果你需要获取所有极值的位置,或者最后一个极值的位置,你需要采取不同的策略,比如结合 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">std::find</pre>
登录后复制
</div> 或手动遍历。</li> <li> <strong>迭代器类型:</strong> 它们接受前向迭代器,这意味着它们不要求随机访问能力,因此可以用于 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">std::list</pre>
登录后复制
</div> 这样的容器。但返回的迭代器类型会与传入的迭代器类型一致,例如,如果传入 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">const_iterator</pre>
登录后复制
</div>,则返回 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">const_iterator</pre>
登录后复制
</div>。</li> <li> <strong>比较器的选择:</strong> 使用自定义比较器时,一定要确保它满足严格弱序的要求。一个常见的错误是比较器没有处理好相等的情况,或者不满足传递性,这会导致结果不确定。我个人在写比较器时,总是倾向于使用简单的 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">a.member < b.member</pre>
登录后复制
</div> 形式,这最不容易出错。</li> <li> <strong>性能考量:</strong> 尽管 O(N) 已经很高效,但在一些对性能极其敏感的场景下,尤其是在内循环中,如果能通过其他方式(比如在数据插入时就维护极值,或者使用专门的数据结构)避免反复调用 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div> 或 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div>,那会是更好的选择。但这通常是过度优化,对于大多数日常任务来说,直接使用这两个算法是清晰且性能足够的。</li> </ol> <p>总的来说,<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">min_element</pre>
登录后复制
</div> 和 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">max_element</pre>
登录后复制
</div> 是 C++ STL 中非常实用且可靠的工具,理解它们的工作原理和注意事项,能帮助我们更高效、更安全地编写代码。</p>

以上就是C++STL算法min_element和max_element使用的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号