stl中的比较最大最小操作
- 一、概述
- 二、最小值
- 1. min
- 2. min_element
- 三、最大值
- 1. max
- 2. max_element
- 四、混合
- 1. minmax
- 2. minmax_element
一、概述
记录这里C11中常用的最小值和最大值的比较函数,最好的参考资料其实就是 https://zh.cppreference.com
最重要的查看文档其实就看他的如何实现,这个就是使用的最常用的功能。因为STL用的很多基本上全是函数模板库,都是支持自定义函数函数器作为一个对比选项。
不带 _element 的函数一般用在两个值之间比较,如果很多值,还是用带_element ,这个是去遍历容器比较
就像min、max最后比较两个值,而且返回的是值,min_element、max_element比较容器,返回的是迭代器
二、最小值
1. min
1. 可能的实现
// 版本 1
template<class T>
const T& min(const T& a, const T& b)
{return (b < a) ? b : a;
}// 版本 2
template<class T, class Compare>
const T& min(const T& a, const T& b, Compare comp)
{return (comp(b, a)) ? b : a;
}// 版本 3
template<class T>
T min(std::initializer_list<T> ilist)
{return *std::min_element(ilist.begin(), ilist.end());
}// 版本 4
template<class T, class Compare>
T min(std::initializer_list<T> ilist, Compare comp)
{return *std::min_element(ilist.begin(), ilist.end(), comp);
}
从上面的实现其实就能看出来,这个是支持用函数器做自己的特定对比,也是可以通过重载 < 符号去实现对比功能.
而且输入值和输出的模板类型是一样的,
还有一些用的是 min_element 函数为实现,对了min_element的一个适配器。
- 例子
下面给一个对比最小值的例子
#include <algorithm>
#include <iostream>
#include <string_view>int main()
{int res_1 = std::min(1, 9999); // res_1 = 1char res_2 = std::min('a', 'b'); // res_2 = 'a'string res_3 = std::min({"foo", "bar", "hello"}, [](const std::string s1, const std::string s2){return s1.size() < s2.size();}) ; // res_3 = "foo"
}
min_element_67">2. min_element
看看这个的相关实现
// 版本一
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;
}// 版本二
template<class ForwardIt, class Compare>
ForwardIt min_element(ForwardIt first, ForwardIt last, Compare comp)
{if (first == last)return last;ForwardIt smallest = first;++first;for (; first != last; ++first)if (comp(*first, *smallest))smallest = first;return smallest;
}
从函数的实现来看,外部的函数器的差距就在 一个是用得 ‘<’ ,另外一个用的 comp(*first, *smallest)对比,因为‘<’取决于语言定义或者我们程序员的重载实现的。 后面的其他函数max,minmax都是用的这样的。
这个参数的传入的其实就是迭代器,返回的也是迭代器也需要去解引取值之类的。
就像下面这种代码
std::vector<PointF> points{PointF{-1.43, 5.654}, PointF{2.453, 8.654} , PointF{10.453, -2.654}, PointF{14.453, -8.87}};auto x_minmax = std::minmax_element(points.begin(), points.end(), [](const PointF &p1, const PointF &p2){return p1.x() < p2.x();
}) ;
三、最大值
1. max
max和min是一样的定义方式,其实就是把那个大于小于改了一下
2. max_element
这个的实现也比较简单
// 版本一
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;
}// 版本二
template<class ForwardIt, class Compare>
ForwardIt max_element(ForwardIt first, ForwardIt last, Compare comp)
{if (first == last)return last;ForwardIt largest = first;++first;for (; first != last; ++first)if (comp(*largest, *first))largest = first;return largest;
}
四、混合
1. minmax
实现的源码大差不差的如下,是不是比较巧妙和灵活,注意这个是返回的是值,而不是迭代器
//版本一
template<class T>
constexpr std::pair<const T&, const T&> minmax( const T& a, const T& b )
{return (b < a) ? std::pair<const T&, const T&>(b, a): std::pair<const T&, const T&>(a, b);
}//版本二
template<class T, class Compare>
constexpr std::pair<const T&, const T&> minmax( const T& a, const T& b, Compare comp )
{return comp(b, a) ? std::pair<const T&, const T&>(b, a): std::pair<const T&, const T&>(a, b);
}//版本三
template< class T >
constexpr std::pair<T, T> minmax( std::initializer_list<T> ilist )
{auto p = std::minmax_element(ilist.begin(), ilist.end());return std::pair(*p.first, *p.second);
}// 版本四
template< class T, class Compare >
constexpr std::pair<T, T> minmax( std::initializer_list<T> ilist, Compare comp )
{auto p = std::minmax_element(ilist.begin(), ilist.end(), comp);return std::pair(*p.first, *p.second);
}
上面的first是小值,second是大值,所以看一下源码就记住了
看看例子
std::pair<int, int> bounds = std::minmax(3, -1);
2. minmax_element
和之前的min_element类似,返回的是一个std::pair<迭代器,迭代器>类型,要取值要自己去解引数据
//版本一
template<class ForwardIt>
std::pair<ForwardIt, ForwardIt> minmax_element(ForwardIt first, ForwardIt last)
{using value_type = typename std::iterator_traits<ForwardIt>::value_type;return std::minmax_element(first, last, std::less<value_type>());
}//版本二
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};
}
例子如下:
std::vector<int> v {3, 1, 4, 1, 5, 9, 2, 6};
auto bounds = std::minmax_element(v.begin(), v.end());int min = *bounds.first; // 1
int max = *bounds.second; // 9