如何在向量中获取最大或最小值?

212

如何在C++中获取向量的最大或最小值?

我是否错误地认为它与数组更或多或少相同?

我需要一个迭代器,是吗?我尝试使用max_element,但一直出错。

vector<int>::const_iterator it;
it = max_element(cloud.begin(), cloud.end());
error: request for member ‘begin’ in ‘cloud’, which is of non-class type ‘int [10]

3
看起来 cloud 不是 STL 容器,而是一个 int[10]。基本上,cloud 没有成员 .begin()。除非你只做这一件事,否则最好去学习一本基础的 C++ 书籍。 - Chris A.
1
还有一些代码可能也很有用。云的定义在哪里? - Tim
13
但是你发布的编译器错误显示:"cloud is of non-class type int[10]",它怎么可能是一个向量呢? - jalf
读者可能会感到困惑,因为标题和标签中都写着“向量”,但实际上并不是,正如其他人在上面评论的那样。至少你可以读一下这些评论... - starriet
10个回答

176

使用C++11/C++0x编译标志,您可以:

auto it = max_element(std::begin(cloud), std::end(cloud)); // C++11

否则,请自行编写:
template <typename T, size_t N> const T* mybegin(const T (&a)[N]) { return a; }
template <typename T, size_t N> const T* myend  (const T (&a)[N]) { return a+N; }

请访问http://ideone.com/aDkhW,即可实时查看相关的IT技术内容:

#include <iostream>
#include <algorithm>

template <typename T, size_t N> const T* mybegin(const T (&a)[N]) { return a; }
template <typename T, size_t N> const T* myend  (const T (&a)[N]) { return a+N; }

int main()
{
    const int cloud[] = { 1,2,3,4,-7,999,5,6 };

    std::cout << *std::max_element(mybegin(cloud), myend(cloud)) << '\n';
    std::cout << *std::min_element(mybegin(cloud), myend(cloud)) << '\n';
}

如果您需要同时获取最小值和最大值,建议使用std::minmax_element(...)函数 :/


你好,你知道是否可以将其应用于维数组或向量吗? - Charles Chow
4
可以的。标准库算法被设计成可以通用地处理迭代器。指针也可以作为迭代器使用。 - sehe
不要忘记包含 <algorithm> 以使用 max_element。 - gordon_freeman
max_element(std::begin(cloud), std::end(cloud)) 相对于 max_element(cloud.begin(), cloud.end()) 有什么优势吗? - starriet
2
@starriet 它不仅支持具有begin()/end()成员函数的标准容器。这正是原始问题的确切主题,因为它使用了一个C风格数组,虽然它可以使用std::begin(arr)但不能使用arr.begin() - sehe

171

如果您想使用函数std::max_element(),那么您需要这样做:

double max = *max_element(vector.begin(), vector.end());
cout<<"Max value: "<<max<<endl;

33
为什么在 *max_element 中有一个 * 符号? - Konrad
76
因为max_element返回的是迭代器。 - Angie Quijano
我猜你假设输入是vector<double>或者*max_element()默认返回double值。 - Samir Kape
4
请确保您始终放置代码片段所需的 #include 文件。此外,将 vector 命名为 "vector" 可能不是一个好主意 - 它并非保留关键字,但相似! - markgalassi
太棒了!谢谢你的回答。更加简洁明了,而且确实解答了问题。 - Klim Yadrintsev
在这种情况下使用“vector”作为向量名称会引起混乱...狗和猫生活在一起...大规模的恐慌。 - Morc

27

 #include <vector>

 vector<int> v {1, 2, 3, -1, -2, -3};

如果向量按升序或降序排序,则可以以O(1)的复杂度找到它。

对于一个升序向量,第一个元素是最小的元素,可以通过v[0](从0开始计数)获得,而最后一个元素是最大的元素,可以通过v[sizeOfVector-1]获得。

如果向量按降序排序,则最后一个元素是最小的元素,可以通过v[sizeOfVector-1]获得,而第一个元素是最大的元素,可以通过v[0]获得。

如果向量未排序,则必须遍历整个向量才能获取最小/最大元素。在这种情况下,时间复杂度为O(n),其中n是向量的大小。

int smallest_element = v[0]; //let, first element is the smallest one
int largest_element = v[0]; //also let, first element is the biggest one
for(int i = 1; i < v.size(); i++)  //start iterating from the second element
{
    if(v[i] < smallest_element)
    {
       smallest_element = v[i];
    }
    if(v[i] > largest_element)
    {
       largest_element = v[i];
    }
}

您可以使用迭代器,

for (vector<int>:: iterator it = v.begin(); it != v.end(); it++)
{
    if(*it < smallest_element) //used *it (with asterisk), because it's an iterator
    {
      smallest_element = *it;
    }
    if(*it > largest_element)
    {
      largest_element = *it;
    }
}

当您需要在给定向量中查找最小或最大元素时,您可以在输入部分进行计算。

int smallest_element, largest_element, value;
vector <int> v;
int n;//n is the number of elements to enter
cin >> n;
for(int i = 0;i<n;i++)
{
    cin>>value;
    if(i==0)
    {
        smallest_element= value; //smallest_element=v[0];
        largest_element= value; //also, largest_element = v[0]
    }

    if(value<smallest_element and i>0)
    {
        smallest_element = value;
    }

    if(value>largest_element and i>0)
    {
        largest_element = value;
    }
    v.push_back(value);
}

你也可以通过内置函数获得最小/最大元素

#include<algorithm>

int smallest_element = *min_element(v.begin(),v.end());

int largest_element  = *max_element(v.begin(),v.end());

您可以使用这些函数来获取任何范围内的最小/最大元素,例如:

vector<int> v {1,2,3,-1,-2,-3};

cout << *min_element(v.begin(), v.begin() + 3); //this will print 1,smallest element of first three elements

cout << *max_element(v.begin(), v.begin() + 3); //largest element of first three elements

cout << *min_element(v.begin() + 2, v.begin() + 5); // -2, smallest element between third and fifth element (inclusive)

cout << *max_element(v.begin() + 2, v.begin()+5); //largest element between third and first element (inclusive)

我曾在使用 c++ 的 min_element()/max_element() 函数之前,使用过星号 (*) 来取得 iterator。

All codes are in c++.


2
min_elementmax_element返回的是迭代器,而不是指针。然而,从技术上讲,指针是迭代器的一个子集。请参见:https://dev59.com/NnE85IYBdhLWcg3wikEu - rayryeng

18

你可以直接使用 max_elementmin_element 函数进行打印。

例如:

cout << *max_element(v.begin(), v.end());

cout << *min_element(v.begin(), v.end());

12

假设云是int cloud[10],您可以像这样完成: int *p = max_element(cloud, cloud + 10);


我也要试试这个。之前我尝试过获取最大元素,但没有成功。谢谢! - bob blob

4
在C++11中,你可以使用一些类似以下的函数:
int maxAt(std::vector<int>& vector_name) {
    int max = INT_MIN;
    for (auto val : vector_name) {
         if (max < val) max = val;
    }
    return max;
}

2
既然你在引用C++11,那么使用它比使用std::max_element更好的原因是什么? - rayryeng
为什么标准库中已经有内置/标准算法了? - Peter Mortensen

2
如果您想使用迭代器,可以使用数组进行placement-new
std::array<int, 10> icloud = new (cloud) std::array<int,10>;

请注意末尾缺少(),这很重要。这将创建一个使用该内存作为其存储的数组类,并具有迭代器等STL功能。
(顺便说一下,这是C++ TR1/C++11)

new 返回一个指针,而不是一个值——所以 std::array<int, 10> icloud = new ... 是编译错误。此外,一旦您调用任何类型的 new(包括放置 new),而没有初始化值,检查这些值就是未定义行为。即使这在相同大小的值数组的顶部,读取这些值也违反了标准,编译器可以自由地将此代码视为无效(可能会对其进行优化、删除等)。 - Human-Compiler

2
您可以使用max_element在向量中获取最大值。 max_element返回一个迭代器,指向范围内的最大值,如果范围为空,则返回最后一个。由于迭代器类似于指针(或者可以说指针是迭代器的一种形式),您可以在它之前使用*来获取该值。 因此,根据问题,您可以在向量中获取最大元素:
int max=*max_element(cloud.begin(), cloud.end());

它将为您的向量“cloud”提供最大元素。 希望有所帮助。

请确保您始终放置代码片段所需的 #include 文件。 - markgalassi

2

代表作者回答

for (unsigned int i = 0; i < cdf.size(); i++)
  if (cdf[i] < cdfMin)
    cdfMin = cdf[i];

其中cdf是一个向量。


1

就这样:

// assuming "cloud" is:
// int cloud[10]; 
// or any other fixed size

#define countof(x) (sizeof(x)/sizeof((x)[0]))

int* pMax = std::max_element(cloud, cloud + countof(cloud));

为什么要使用宏?没有理由!错误始于 int cloud[10];,这是使用魔法数字的原因。 - Ulrich Eckhardt
1
因为错误信息清楚地表明他没有向量,而是普通数组。你必须想办法计算它的长度,以避免使用硬编码的魔数。他将来可能会改变长度,但是用这种方式找到最大值的代码将保持不变。 - ivan.ukr
抱歉,这个信息传达得不太准确。你的解决方案是正确的,但是不好。原因是它假设使用了魔数,而这并不符合错误信息。然后它继续使用宏,这总是一种代码异味。 - Ulrich Eckhardt
理论上,宏可以展开为代码,但我更喜欢将其保留为一种罕见的“有用”宏。此外,一些供应商甚至在OOB中执行此操作。例如,Visual C++提供了类似于上面的OOB“_countof”。如果您知道如何使用元编程完成相同的操作,但是代码短小而优雅,请发布您的代码示例。 - ivan.ukr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接