Modalwert aus Vector finden (Stroustrup)



  • enf elem schrieb:

    Sortieren ist langsam. Den Median erhält man mit std::nth_element .

    Vom Median ist ja auch nicht die Rede.



  • Ich hab jetzt noch was mit sortieren zu bieten:

    int main()
    {
        vector<int> val {4,0,4,2,2,4,5,33};
        sort(val.begin(),val.end());
        int m=0;
        for (int i=0; i<val.size(); ++i)
        {
            if (val[i]==val[i+1])
                m=val[i];
        }
        cout<<"Modalwert="<<m;
    }
    

    Ist das Ok soweit?



  • Du brauchst die #includes und das using namespace std; nicht abzuschneiden. Das macht copy und paste nur umständlicher für alle, die Deinen Code kompiliern möchten.

    Es gibt neben operator[]() noch den Zugriff auf Vektorelemente mit at() . at() kontrolliert ob der Index auf den zugegriffen wird gültig ist.
    Da gibt es dann eine Überraschung, wenn Du Z. 8 und 9 ersetzt:

    if (val.at(i)==val.at(i+1))
                m=val.at(i);
    


  • Ist das Ok soweit?

    Nein, du liest jenseits der Vectorgrenzen:

    for (int i=0; i<val.size(); ++i)
    {
        if(val[i]==val[i+1])
                   // ^^^^^ da
            m=val[i];
    }
    

    Davon abgesehen ist deine Implementierung auch falsch. Versuch mal diesen vector:

    {0, 2, 4, 0, 0, 0, 0, 0, 2, 4}
    

    Dein Algorithmus sucht die letzte Zahl, die mindestens zweimal vorkommt.

    Vorgehensweise: Sortieren, zählen bis eine neue Zahl kommt. Dann neu zählen. Wenn die neue Zahl öfter vorkommt, als die alte: neue Zahl merken, neue Anzahl merken, weitermachen.



  • nächster Versuch:

    // Modalwert aus Reihe ganzer positiver Zahlen
    #include<iostream>
    #include<string>
    #include<vector>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int main()
    {
        vector<int> val {0, 2, 4, 0, 0, 0, 0, 0, 2, 4};
        sort(val.begin(),val.end());
        int counter_old=0;
        int counter_new=0;
        int cur_max=0;
        for (int i=0; i<val.size(); ++i)
        {
            if (i>0 && val[i]==val[i-1])        // Wenn 2. Wert im Vektor gleich dem 1.
            {
                counter_old=++counter_old;      // alten Zähler erhöhen
                if (counter_old>counter_new)    // wenn alter Zähler größer Vektorwert in cur_max speichern
                {
                    cur_max=val[i];
                    counter_new=counter_old;
                }
            }
            else
                counter_old=0;                  // Wenn Vektor Paar ungleich alten Zähler zurücksetzen
        }
        cout<<"M="<<cur_max<<endl;
    }
    


  • pauledd schrieb:

    nächster Versuch:

    if (i>0 && val[i]==val[i-1])        // Wenn 2. Wert im Vektor gleich dem
    

    Selbst, wenn du es hier mit i>0 abfängst es ist immer eine schlechte Idee im Vector vor oder zurückzugucken.

    Guck Dir mal die Lösung an die ich geschrieben habe und tausch die iteratoren einfach mit richtigen ints aus oder merk dir die last_number einfach.
    Du kannst es natürlich auch mit einem bool lösen aber +1 , -1 im Vector ist selbst mit abfangen eine schlechte Lösung. (Nach meiner Meinung)

    Wenn du es mit iteratoren machst musst du nicht kopieren ansonsten kopier, das int einfach das kostet nichts.



  • Ok ich schau mir nochmal dein Code an. Aber ich denke ich habe die Aufgabe im Rahmen der bisher behandelten Mittel des Buches gelöst da ich den Begriff "Iterator" bzw. "const_iterator" noch nicht gelesen habe (kommt irgendwo ab Seite 700 :D, bin auf Seite 155).

    Ein paar Fragen zu deinem Code:

    warum schreibst du eigentlich immer das

    std::
    

    davor?

    was macht das auto in ?

    for (auto cit...
    

    was macht das * hier?

    if (*cit == *last_number)
    


  • pauledd schrieb:

    std::
    

    davor?

    Das ist einfach Gewohnheit, da ich schon oben using namespace std; geschrieben habe ist es eigentlich nicht nötig.
    Wenn du deinen Source -Code in Header(hpp) und CPP files trennst, wirst du die using deklarationen, wenn überhaupt nur im cpp File haben.

    pauledd schrieb:

    was macht das auto in ?
    C++:

    for (auto cit...
    

    auto ist einfach etwas für Schreibfaule, gerade bei iteratoren ist es manchmal ziemlich anstrengend den Typ genau aufzuschreiben.

    std::cbegin(val); // returned einen vector<int>::const_iterator
                      // das auto macht es überflüssig es explizit hinzuschreiben
    for (auto cit = std::cbegin(val);
    // und
    for (std::vector<int>::const_iterator cit;
    // sind das gleiche, das andere ist aber kürzer
    

    pauledd schrieb:

    was macht das * hier?

    if (*cit == *last_number)
    

    Wahrscheinlich bist du in deinem Buch noch nicht zu Pointern gekommen.
    Ein iterator ist ein Objekt der in einem Container auf ein gewisses Objekt zeigt.
    Wenn ich einfach "==" ohne "" verwenden würde, würde ich den Computer fragen sind die Iteratoren cit und last_number gleich.
    Mit anderen Worten zeigen die beiden Iteratoren auf das gleiche Element im Container.
    Ich möchte aber wissen ob das Value auf, dass sie zeigen gleich ist und dafür muss ich den Iterator mit "
    " dereferenzieren.

    Ich hoffe, dass war halbwegs verständlich.



  • Das mit den Iteratoren kannste dir so vorstellen:

    int begin = 0u; // Iterator auf Anfang: vector<int>::iterator begin = vec.begin();
    int end = vec.size(); // Iterator auf Ende: vector<int>::iterator end = vec.end()
    ++begin; // gehe zum nächsten Element: ++begin
    vec[begin]; // lese Wert an Stelle begin: *begin
    begin == end; // vergleiche die Position von begin mit end: begin == end
    


  • Ruvi schrieb:

    Wahrscheinlich bist du in deinem Buch noch nicht zu Pointern gekommen.

    So ist es.

    So ganz erschließt sich mir das noch nicht aber vielen Dank für eure
    Erläuterungen. Ich werde diesen Thread sicher nocheinmal aufsuchen
    und dann mit fortgeschrittenem Wissen herangehen.


Anmelden zum Antworten