Felder zusammenfügen, sortieren und Häufigkeit ermitteln



  • Hallo
    Ich möchte gern die Werte von Liste_1 und Liste_2 zusammenfügen, sortieren und die Anzahl von den Werten die mehrfach drin vorkommen speichern. Es sollte dann so aussehen.

    Liste_Neu      Anzahl
        0            3
        1            4
        3            3
        7            3
       10            1
    

    Das Sortieren bekommt man ja mit Bubblesort hin aber dazu müsste ich die Werte von Liste_1 und Liste_2 erstmal in Liste_Neu bekommen.

    struct Tabelle
    {
        int    Liste_1;           //Werte: 1,0,3,1,7,0,10
        int    Liste_2;           //Werte: 3,1,0,7,3,7,1
        int    Liste_Neu;
        int    Anzahl;
    };
    

    Es ist sicher bestimmt total einfach aber ich weiss überhaupt nicht wie ich es umsetzten soll.
    Ich bin für jeden Vorschlag offen.
    Danke



  • Dazu solltest du mit Arrays arbeiten.
    Das zusammenführen kannst du
    a) selber machen (eine for-Schleife)
    b) mit memcpy
    c) oder gleich mit einem angepassten Mergesort (Die Anpassung wäre halt das mitzählen)

    Willst du wirklich alle drei Felder in einer struct halten?



  • zu a) Wenn ich die zusammenführe wird entweder der Wert überschrieben oder in der Liste_Neu kommen erst die Werte von Liste_1 und danach die Werte von Liste_2. Damit könnte ich ja auch noch leben wenn dann die Werte rausfallen würden die mehrfach erscheinen.

    zu b) void* memcpy( void* dest, const void* src, size_t count ); hab ich das gefunden aber versteh es nicht richtig. Hast du ein verständliches Beispiel davon?!

    Und ich muss mit der struct Arbeiten. Brauch sie vorher und später noch mal in meinem Programm.
    Aber ich könnte das extra schreiben das ist kein Problem.

    struct Tabelle_2
    {
        int    Liste_Neu;
        int    Anzahl;
    };
    


  • zauberpeter schrieb:

    zu b) void* memcpy( void* dest, const void* src, size_t count ); hab ich das gefunden aber versteh es nicht richtig. Hast du ein verständliches Beispiel davon?!

    Das scheint eine maschinelle Übersetzung zu sein...
    Furchtbar!

    Klick auf der Site mal unten auf Englisch bei "In anderen Sprachen".
    Da ist dann auch ein Beispiel.



  • zauberpeter schrieb:

    Ich möchte gern die Werte von Liste_1 und Liste_2 zusammenfügen, sortieren und die Anzahl von den Werten die mehrfach drin vorkommen speichern.
    ...
    Das Sortieren bekommt man ja mit Bubblesort hin aber dazu müsste ich die Werte von Liste_1 und Liste_2 erstmal in Liste_Neu bekommen.

    Das hört sich erstmal so an, dass du Probleme mit dem zusammenfügen hast.

    zauberpeter schrieb:

    Damit könnte ich ja auch noch leben wenn dann die Werte rausfallen würden die mehrfach erscheinen.

    Schau dir doch mal Mergesort an. Da gibt es auch Videos dazu: https://www.youtube.com/watch?v=EeQ8pwjQxTM oder auch https://www.youtube.com/watch?v=XaqR3G_NVoo

    Und du hast immer noch keine Arrays. Deine "Listen" (_1, _2 und _Neu) können nur einen Wert aufnehmen.

    Sinnvoller wäre etwas wie

    struct Tabelle
    {
        int    Liste[Wieviel_Werte_brauchst_du];
        int    Anzahl;
    };
    

    Das dann für jede Liste:

    struct Tabelle Liste_1;
        struct Tabelle Liste_2;
        struct Tabelle Liste_Neu;
    

    Und wenn alles doch in einer struct sein soll, dann so:

    struct Tabellen
    {
        struct Tabelle Liste_1;
        struct Tabelle Liste_2;
        struct Tabelle Liste_Neu;
    };
    


  • DirkB schrieb:

    Schau dir doch mal Mergesort an. Da gibt es auch Videos dazu: https://www.youtube.com/watch?v=EeQ8pwjQxTM oder auch https://www.youtube.com/watch?v=XaqR3G_NVoo

    Ohh mein Gott das 2. Video ist so Klasse 😃

    DirkB schrieb:

    Und du hast immer noch keine Arrays. Deine "Listen" (_1, _2 und _Neu) können nur einen Wert aufnehmen.

    Ja ich hätte mich vllt besser ausdrücken sollen. Hab es in meinem Programm anders. Aber egal wir können ja einfach davon ausgehen das, wie du schon beschrieben hast, es auch so geht

    struct Tabelle
    {
        int    Liste[Wieviel_Werte_brauchst_du];
        int    Anzahl;
    };
    struct Tabelle Listen[ANZAHL]
    

    Und dadurch das ich die "[ANZAHL]/[Wieviel_Werte_brauchst_du]" nicht weiss müsste man es ja dynamisch machen?!

    Wenn ich doch wenigstens erstmal nur erstmal die Werte wie im Bsp reinbekommen würde.

    Liste_Neu      
        0           
        1 
        3 
        7 
       10
    

    Danach könne ich ja noch mal schauen wieviel mal was in den beiden Listen(Liste_1,Liste_2)vorkommt.



  • Ich habe jetzt zwar erstmal alle Werte hintereinander geschrieben aber muss erstmal reichen.
    Das habe ich bis jetzt.

    int Wort[]={1,0,3,1,7,0,10,3,1,0,7,3,7,1};
        int Wort_Anzahl=14;                                      //Dynamisch ABER wie?!
        int Min,Max,Feld,*Z_Feld,j,k,i=0;
    
        //Min und Max ermitteln
        for (i=1; i<Wort_Anzahl; i++)
        {
            if (Wort[i]<Min) Min=Wort[i];
    
            if (Wort[i]>Max) Max=Wort[i];
        }
    
        //Zählen, Sortieren
        Feld=Max-Min+1;
        Z_Feld=(int*)calloc(Feld,sizeof(int));
    
        for (i=0; i<Wort_Anzahl; i++)
        {
            Z_Feld[Wort[i]-Min]++;
        }
        for (i=0,k=0; i<Feld; i++)
        {
            for (j=0; j<Z_Feld[i]; j++, k++)
            {
                Wort[k]=i+Min;
                printf("Wert %i Anzahl %i\n",Wort[k],Z_Feld[k]);
            }
        }
    

    Das "int Wort_Anzahl=14;" würde ich gern noch Dynamisch hinbekommen. Aber wie?!

    Ausgabe

    Wert 0 Anzahl 3
    Wert 0 Anzahl 4
    Wert 0 Anzahl 0
    Wert 1 Anzahl 3
    Wert 1 Anzahl 0
    Wert 1 Anzahl 0
    Wert 1 Anzahl 0
    Wert 3 Anzahl 3
    Wert 3 Anzahl 0
    Wert 3 Anzahl 0
    Wert 7 Anzahl 1
    Wert 7 Anzahl 0
    Wert 7 Anzahl 0
    Wert 10 Anzahl 0
    

    Jetzt muss ich nur noch bei der "Anzahl" Ausgabe die 0 wegbekommen und bei der "Werte" Ausgabe die vielfachen Werte wegbekommen.



  • zauberpeter schrieb:

    Und dadurch das ich die "[ANZAHL]/[Wieviel_Werte_brauchst_du]" nicht weiss müsste man es ja dynamisch machen?!

    Ich dacht nicht, dass du schon damit umgehen kannst.

    zauberpeter schrieb:

    Wenn ich doch wenigstens erstmal nur erstmal die Werte wie im Bsp reinbekommen würde.

    Erst die Liste_1 nach Liste_Neu kopieren und dann Liste_2 dahinter.

    int    Liste_1[] ={ 1,0,3,1,7,0,10 };
        int    Liste_2[] ={ 3,1,0,7,3,7,1 };
        int    Liste_Neu[100];
        int    Anz_Neu;
    
        int i;
        for(i = 0; i < sizeof(Liste_1)/(sizeof(Liste_1[0]); i++)
           Liste_Neu[i]=Liste_1[i];
        for(int j = 0 ; j < sizeof(Liste_2)/(sizeof(Liste_2[0]); j++,i++)
           Liste_Neu[i]=Liste_2[j];
        Anz_Neu = i;
    

    zauberpeter schrieb:

    Das "int Wort_Anzahl=14;" würde ich gern noch Dynamisch hinbekommen. Aber wie?!

    Siehst du zweimal oben im Code.

    Feld=Max-Min+1; ist etwas ungünstig, wenn du große Zahlenwerte im Feld hast.

    zauberpeter schrieb:

    Jetzt muss ich nur noch bei der "Anzahl" Ausgabe die 0 wegbekommen und bei der "Werte" Ausgabe die vielfachen Werte wegbekommen.

    Dann lass doch die innerste Schleife weg.
    Die Angabe für 10 stimmt nicht. WArum änderst du Wort[k] in der Schleife?
    Und es gibt das if-Statement, falls du irgendwelche Sachen besonders behandeln willst.



  • Ah ich dank dir. Hat mir sehr weitergeholfen und wieder was neues gelernt 😉

    DirkB schrieb:

    WArum änderst du Wort[k] in der Schleife?
    Und es gibt das if-Statement, falls du irgendwelche Sachen besonders behandeln willst.

    Ja hab ich hinbekommen.

    //Zählen, Sortieren
        Feld=Max-Min+1;
        Z_Feld=(int*)calloc(Feld,sizeof(int));
    
        for (i=0; i<Wort_Anzahl; i++)
        {
            Z_Feld[Knoten_Liste[i]-Min]++;
        }
        for (i=0,k=0; i<Feld; i++)
        {
            for (j=0; j<Z_Feld[i]; j++, k++)
            {
                if (Z_Feld[k]!=0)
                {
                    printf("Wert %i Anzahl %i\n",Knoten_Liste[k],Z_Feld[k]);
                }
    
            }
        }
    

    Nun fehlt nur noch das ich in der Ausgabe die Zahlen richtig einzeln geordnernet bekommen.
    Jetzt bekomm ich das raus.

    Wert 1 Anzahl 3
    Wert 0 Anzahl 4
    Wert 1 Anzahl 3
    Wert 3 Anzahl 3
    Wert 7 Anzahl 1
    

    Und haben möchte ich

    Wert 0  Anzahl 3
    Wert 1  Anzahl 4
    Wert 3  Anzahl 3
    Wert 7  Anzahl 3
    Wert 10 Anzahl 1
    

  • Mod

    Ein paar Lösungsansätze:
    -Einfach umzusetzen, aber ineffizient (für solch kleine Mengen aber gut genug): Liste erst sortieren, danach ist es einfach, die gleichen Werte zu zählen. Dies ist leicht umzusetzen, da Sortieren mit der Standardbibliothek geht (qsort). Da das Sortieren aber letztlich unnötig ist (es macht bloß das Zählen sehr einfach), verplempert man viel Rechenzeit für diese aufwändige Operation.

    -Einfach umzusetzen, sehr effizient, aber sehr eingeschränkt einsetzbar: Ein hinreichend großes Array mit Nullen füllen (im folgenden Zählarray genannt). Dann die Daten durchgehen. Für jede Zahl erhöht man den Wert an der entsprechenden Stelle im Zählarray um 1. Am Ende kann man die Häufigkeit der Daten im Zählarray direkt ablesen. Funktioniert aber nur mit positiven Ganzzahlen als Daten und man muss vorher wissen, wie groß die Werte werden.

    -Einfach umzusetzen, sehr effizient, aber eingeschränkt einsetzbar: Wie oben, aber das Zählarray ist dynamisch. So muss man vorher nicht wissen, wie groß die zahlen werden. Aber sie dürfen insgesamt nicht sehr groß werden, sonst geht einem der Speicher für das Zählarray aus.

    -Ohne externe Bibliotheken in C schwer umzusetzen, sehr effizient, sehr universell einsetzbar: Anstatt eines Zählarrays benutzt man eine assoziative Datenstruktur. Jedem Wert wird dabei dynamisch eine Zählvariable zugeordnet. Am Ende kann man die Häufigkeiten direkt aus der Datenstruktur ablesen. Funktioniert für sämtliche Arten von Daten. Solche Datenstrukturen gibt es in vielen Sprachen fix und fertig, in C muss man das aber selber Programmieren. Link zur Einführung: http://en.wikipedia.org/wiki/Associative_array



  • Nochmal etwas anderes

    int Min,Max,Feld,*Z_Feld,j,k,i=0;
    
    // Welchen Wert haben Min und Max an dieser Stelle?
    // Ganz sicher?
    
        for (i=1; i<Wort_Anzahl; i++)
        {
            if (Wort[i]<Min) Min=Wort[i];  // Welche Warnung gibt der Compiler für diese Zeile
    
            if (Wort[i]>Max) Max=Wort[i];  // Welche Warnung gibt der Compiler für diese Zeile
        }
    


  • Keine Warnung. Es Funktioniert so aber wie oben schon genannt ist es nicht sinnvoll dies zu verwenden bei großen Daten.



  • Du hast die Frage nicht beantwortet.

    Fehlen da Zeilen?

    Du weist Min und Max vor dem Vergleich keinen Wert zu. Dann können die irgendwelche Werte haben.
    Dann fängst du aber auch erst bei Wort[1] mit der Suche an. Was ist mit Wort[0]?



  • Stimmt du hast recht. Hab jetzt von i=0 angefangen und Min und Max nix zugewiesen. Wenn ich denen 0 zuweise und dann in den Listen keine Null vorkommt würde er ja für Min 0 annehmen und es wäre falsch.
    Was ich jetzt noch nicht ganz hinbekomme ist Liste_1 und Liste_2 die Sachen aus meiner Struktur zu übergeben mit diesem sizeof.

    struct Listen
    {
        int    Wert1;     //Hier steht drin {1,0,3,1,7,0,10};
        int    Wert2;     //Hier steht drin {3,1,0,7,3,7,1};
    };
    
        int    Liste_1[] ={1,0,3,1,7,0,10};
        int    Liste_2[] ={3,1,0,7,3,7,1};
        int    Liste_Neu[100];
        int    Anz_Neu;
    
        int i;
        for(i = 0; i < sizeof(Liste_1)/(sizeof(Liste_1[0]); i++)
           Liste_Neu[i]=Liste_1[i];
        for(int j = 0 ; j < sizeof(Liste_2)/(sizeof(Liste_2[0]); j++,i++)
           Liste_Neu[i]=Liste_2[j];
        Anz_Neu = i;
    


  • zauberpeter schrieb:

    Stimmt du hast recht. Hab jetzt von i=0 angefangen und Min und Max nix zugewiesen. Wenn ich denen 0 zuweise und dann in den Listen keine Null vorkommt würde er ja für Min 0 annehmen und es wäre falsch.

    Dann haben Min und Max zufällige Werte (kann auch 0 sein). Wie soll denn da der erste Vergleich funktionieren?
    Weise Min und Max den ersten Wert des Feldes zu. Beiden denselben Wert, denn der kommt auf alle Fälle im Feld drin vor.
    Dann kannst du auch wieder bei 1 beginnen.

    zauberpeter schrieb:

    Was ich jetzt noch nicht ganz hinbekomme ist Liste_1 und Liste_2 die Sachen aus meiner Struktur zu übergeben mit diesem sizeof.

    struct Listen
    {
        int    Wert1;     //Hier steht drin {1,0,3,1,7,0,10};
        int    Wert2;     //Hier steht drin {3,1,0,7,3,7,1};
    };
    
        int    Liste_1[] ={1,0,3,1,7,0,10};
        int    Liste_2[] ={3,1,0,7,3,7,1};
        int    Liste_Neu[100];
        int    Anz_Neu;
     
    ...
    

    Geht nicht, da du immer noch keine Arrays hast.
    Es gibt auch keinen Platz für die Anzahl.

    BTW: Das Array kann auch größer sein, als die Anzahl der Werte, die du darin speicherst.
    Du solltest dir also diese Anzahl für jedes Array merken.



  • 👍
    Min=Max=Liste_Neu[0];

    DirkB schrieb:

    BTW: Das Array kann auch größer sein, als die Anzahl der Werte, die du darin speicherst.
    Du solltest dir also diese Anzahl für jedes Array merken.

    Ok werde ich machen. Ich dank dir auf alle fälle schon mal für alles und wünsch dir Frohe Ostern 🙂


Anmelden zum Antworten