Verwenden von std :: max_element für einen Vektor <double>

75

Ich versuche, die Min- und Max-Elemente in einem Doppelvektor zu verwenden std::min_elementund std::max_elementzurückzugeben. Meinem Compiler gefällt nicht, wie ich sie derzeit verwenden möchte, und ich verstehe die Fehlermeldung nicht. Ich könnte natürlich meine eigene Prozedur schreiben, um das Min / Max zu finden, aber ich würde gerne verstehen, wie man die Funktionen benutzt.

#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;
}

Hier ist der Compilerfehler:

../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

Würde jemand bitte erklären, was ich falsch mache?

synaptik
quelle
4
Beachten Sie, dass Sie C ++ 11 nur verwenden können std::minmax_element.
GManNickG
@ GManNickG: Ich wusste nichts von dieser Funktion. Ich habe meiner Antwort eine Notiz hinzugefügt, um dies zu berücksichtigen, da das Verhalten anders ist.
Johnsyweb

Antworten:

106

min_elementund max_elementIteratoren zurückgeben, keine Werte. Also brauchst du *min_element...und *max_element....

David Schwartz
quelle
24
Ein Iterator ist insofern ein Zeiger, als er auf Dinge zeigt. Aber es kann ein gewöhnlicher Zeiger sein oder auch nicht. Wenn ein Iterator beispielsweise auf ein Objekt in einer Liste verweist, zeigt es durch Inkrementieren auf das nächste Objekt in der Liste. Das Inkrementieren eines gewöhnlichen Zeigers gilt nur für Sammlungen wie einen Vektor, deren Inhalt garantiert in Sequenzspeicheradressen gespeichert wird.
David Schwartz
2
Wenn der Vektor leer ist, wird ein *max_elementFehler ausgelöst. Gibt es eine Lösung für dieses Problem? Im Moment überprüfe ich, ob der Vektor leer ist oder nicht und benutze dann*max_element
Moj
Ich denke, das ist die beste Lösung. Sie müssen den Fall ohnehin speziell behandeln, da kein vernünftiger Wert zurückgegeben werden kann.
David Schwartz
3
@ Moj: Sie können den Iterator gegen überprüfen C.end().
Intelfx
56

Wie schon andere gesagt haben, std::max_element()und std::min_element()Rückkehr Iteratoren , die werden müssen dereferenziert die erhalten Wert .

Der Vorteil der Rückgabe eines Iterators (und nicht nur des Werts) besteht darin, dass Sie die Position des (ersten) Elements im Container mit dem maximalen (oder minimalen) Wert bestimmen können.

Zum Beispiel (der Kürze halber C ++ 11 verwenden):

#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;
}

Dies ergibt:

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

Hinweis:

Die Verwendung std::minmax_element()wie in den obigen Kommentaren vorgeschlagen kann bei großen Datenmengen schneller sein, jedoch zu geringfügig unterschiedlichen Ergebnissen führen. Die Werte für mein Beispiel oben wären die gleichen, aber die Position des "max" -Elements wäre 9da ...

Wenn mehrere Elemente dem größten Element entsprechen, wird der Iterator zum letzten Element zurückgegeben.

Johnsyweb
quelle
2
@ Synaptik: Dies sollte auch mit anderen Containertypen funktionieren :)
Johnsyweb
26

min / max_element gibt den Iterator an das min / max-Element zurück, nicht an den Wert des min / max-Elements. Sie müssen den Iterator dereferenzieren, um den Wert herauszuholen und einem Double zuzuweisen. Das ist:

cLower = *min_element(C.begin(), C.end());
Maisstängel
quelle