Вопрос по c++, max – Использование std :: max_element для вектора

72

Я пытаюсь использоватьstd::min_element а такжеstd::max_element вернуть элементы min и max в вектор двойников. Моему компилятору не нравится, как я сейчас пытаюсь их использовать, и я не понимаю сообщение об ошибке. Конечно, я мог бы написать свою собственную процедуру для нахождения 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

Кто-нибудь может объяснить, что я делаю не так?

@GManNickG: я не знал об этой функции. Я добавил примечание к своему ответу, чтобы включить это, поскольку поведение отличается. Johnsyweb
Обратите внимание, что если вы используете C ++ 11, вы можете просто использоватьstd::minmax_element. GManNickG

Ваш Ответ

3   ответа
26

iterator к элементу min / max, а не к значению элемента min / max. Вы должны разыменовать итератор, чтобы получить значение и присвоить его двойному. То есть:

cLower = *min_element(C.begin(), C.end());
55

std::max_element() а такжеstd::min_element() вернутьiterators, который должен бытьdereferenced чтобы получитьvalue.

Преимущество возврата итератора (а не только значения) состоит в том, что он позволяет определитьposition (первого) элемента в контейнере с максимальным (или минимальным) значением.

Например (используя 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
Note:

С помощьюstd::minmax_element() как предложено в комментариях выше, может быть быстрее для больших наборов данных, но может дать немного другие результаты.values для моего примера выше было бы то же самое, но позиция "max" элемент будет9 поскольку...

If several elements are equivalent to the largest element, the iterator to the last such element is returned.

@synaptik: Это должно работать и с другими типами контейнеров :)
103

min_element а такжеmax_element возвращают итераторы, а не значения. Так вам нужно*min_element... а также*max_element....

если вектор пуст*max_element поднимает ошибку. Есть ли решение для решения этой проблемы? Прямо сейчас я проверяю, пустой вектор или нет, а затем использую*max_element
Я думаю, что это лучшее решение. В любом случае вам нужно обращаться со случаем специально, потому что нет разумного значения, которое может быть возвращено.
@Moj: вы можете проверить итератор противC.end().
Ах, спасибо! Значит, итератор по сути является указателем? synaptik
Итератор является указателем в том смысле, что он указывает на вещи. Но это может быть или не быть обычным указателем. Например, если итератор ссылается на объект в списке, то при увеличении он указывает на следующий объект в списке. Инкремент обычного указателя выполняется только для коллекций, подобных вектору, которые гарантированно хранят свое содержимое в адресах памяти последовательностей.

Похожие вопросы