Використання std :: max_element на векторі <double>


75

Я намагаюся використовувати std::min_elementі std::max_elementповернути елементи min і max у векторі подвійних. Моєму компілятору не подобається, як я зараз намагаюся їх використовувати, і я не розумію повідомлення про помилку. Звичайно, я міг би написати власну процедуру, щоб знайти мінімум / максимум, але я хотів би зрозуміти, як використовувати функції.

#include <vector>
#include <algorithm>

using namespace std;

int main(int argc, char** argv) {

    double cLower, cUpper;
    vector<double> C;

    // code to insert values in C not shown here

    cLower = min_element(C.begin(), C.end());
    cUpper = max_element(C.begin(), C.end());

    return 0;
}

Ось помилка компілятора:

../MIXD.cpp:84: error: cannot convert '__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >' to 'double' in assignment
../MIXD.cpp:85: error: cannot convert '__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >' to 'double' in assignment

Хтось, будь ласка, пояснить, що я роблю не так?


4
Зверніть увагу, що якщо ви використовуєте C ++ 11, ви можете просто використовувати std::minmax_element.
GManNickG

@GManNickG: Я не знав про цю функцію. Я додав примітку до моєї відповіді, щоб включити це, оскільки поведінка інша.
Johnsyweb,

Відповіді:


106

min_elementі max_elementповертають ітератори, а не значення. Тож потрібно *min_element...і *max_element....


24
Ітератор - це вказівник, який вказує на речі. Але це може бути і не бути звичайним покажчиком. Наприклад, якщо ітератор посилається на об'єкт у списку, збільшуючи його, він вказує на наступний об'єкт у списку. Збільшення звичайного вказівника робить це лише для колекцій, таких як вектор, які гарантовано зберігають свій вміст в адресах пам'яті послідовності.
Девід Шварц,

2
якщо вектор порожній, *max_elementвиникає помилка. Чи є якесь рішення для вирішення цієї проблеми? Зараз я перевіряю, чи порожній вектор чи ні, а потім використовую*max_element
Мой

Я думаю, що це найкраще рішення. У будь-якому випадку вам потрібно вирішити справу спеціально, оскільки немає розумного значення, яке можна повернути.
Девід Шварц

3
@Moj: ти можеш перевірити ітератор C.end().
intelfx

56

Як вже говорили інші, std::max_element()і std::min_element()повертають ітератори , які потрібно розіменовувати, щоб отримати значення .

Перевага повернення ітератора (а не просто значення) полягає в тому, що він дозволяє визначити положення (першого) елемента в контейнері з максимальним (або мінімальним) значенням.

Наприклад (з використанням C ++ 11 для стислості):

#include <vector>
#include <algorithm>
#include <iostream>

int main()
{
    std::vector<double> v {1.0, 2.0, 3.0, 4.0, 5.0, 1.0, 2.0, 3.0, 4.0, 5.0};

    auto biggest = std::max_element(std::begin(v), std::end(v));
    std::cout << "Max element is " << *biggest
        << " at position " << std::distance(std::begin(v), biggest) << std::endl;

    auto smallest = std::min_element(std::begin(v), std::end(v));
    std::cout << "min element is " << *smallest
        << " at position " << std::distance(std::begin(v), smallest) << std::endl;
}

Це дає:

Max element is 5 at position 4
min element is 1 at position 0

Примітка:

Використання, std::minmax_element()як пропонується у коментарях вище, може бути швидшим для великих наборів даних, але може дати дещо інші результати. Ці значення для мого прикладу вище буде те ж саме, але становище «макс» елемент буде 9так ...

Якщо кілька елементів еквівалентні найбільшому елементу, повертається ітератор до останнього такого елемента.


2
@synaptik: Це також має працювати з іншими типами контейнерів :)
Johnsyweb

26

min / max_element повертає ітератор до елемента min / max, а не значення елемента min / max. Вам потрібно провести розстановку ітератора, щоб отримати значення і призначити його подвійному. Це:

cLower = *min_element(C.begin(), C.end());
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.