Sortieren in 2-dimensionalem Array nach 2 Werten!



  • Hallo Leute:
    Ich hab nen 2- Dimensionales Array der Form:
    [5][8][3][2][1]
    [1][3][2][5][1]
    [1][2][1][8][1]
    [4][2][1][8][1]
    ...

    mit Variabler Zeilenlänge, aber fixer Spaltenbreite.

    Ziel ist es, das Array primär nach der ersten Spalte zu sortieren, sekundär nach der Zweiten:

    [1][2][1][8][1]
    [1][3][2][5][1]
    [4][2][1][8][1]
    [5][8][3][2][1]
    Das wäre das gewünschte Ergebnis.

    Ich habe es bereits geschafft primär zu sortieren, aber die *#$% sekundäre Sortierung bring ich nicht hin...

    Code:

    aus privaten Gründen gelöscht
    


  • In Zeile 13 kannst du ein > statt >= benutzen und im Falle von == einfach die nächste Stelle betrachten.
    Zuerst die erste Stelle sortieren und danach die zweite halte ich für ungünstig.

    Oder versuche es mit dem standard qsort. Wenn ich Langeweile habe bastle ich das mit qsort zusammen.



  • nwp2 schrieb:

    Oder versuche es mit dem standard qsort.

    geht bestimmt ganz einfach, mit 'nem 'memcmp' in der compare-funktion.
    🙂



  • Hmm, ja, memcmp wäre nicht schlecht gewesen. Aber auf sowas schlaues komm ich natürlich nicht.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    const int spaltenanzahl = 5;
    int array[][spaltenanzahl] = {5, 8, 3, 2, 1,
    	1, 3, 2, 5, 1,
    	1, 2, 1, 8, 1,
    	4, 2, 1, 8, 1};
    
    int vergleicher(const void *zeile1, const void *zeile2){ //funktion die zwei Zeilen vergleicht und entscheidet welche größer ist
    	const int *z1 = (const int *)zeile1; //das geht auch irgendwie leichter mit einem cast im Parameter aber ich weiß nicht wie
    	const int *z2 = (const int *)zeile2;
    	for (int i = 0; i<spaltenanzahl; i++){
    		if (z1[i]==z2[i]) continue; //diese Stelle ist gleich, wir müssen die nächste vergleichen
    		else return z1[i]>z2[i]; //verschiedene Stelle wurde gefunden
    	}
    	return 0; //alle Stellen sind gleich
    }
    
    int vergleicher2(const void *z1, const void *z2){ //tut quasi dasselbe wie vergleicher
    	return memcmp(z1, z2, spaltenanzahl);
    }
    
    int main(){
    	const int zeilenanzahl = sizeof(array)/sizeof(int)/spaltenanzahl;
    	qsort(array, zeilenanzahl, spaltenanzahl*sizeof(int), vergleicher2); //array sortieren
    	for (int x = 0; x<zeilenanzahl; x++){ //array ausgeben
    		for (int y = 0; y<spaltenanzahl; y++) printf("%d", array[x][y]);
    		printf("\n");
    	}
    	return 0;
    }
    

    Edit: Idee von fricky; geklaut und eingebaut.



  • nwp2 schrieb:

    Hmm, ja, memcmp wäre nicht schlecht gewesen.

    nee, doch nicht. 'memcmp' vergleicht byteweise. die idee war doof (ausser du nimmst char statt int).
    🙂



  • Ups. Tatsächlich. Merkt man nur bei bestimmten Zahlen.

    1  2  1  8  1
    513  3  2  5  1
      4  2  1  8  1
      5  8  3  2  1
    

    Das gilt mit vergleicher2 als geordnet. Das heißt meine Variante Marke Eigenbau war doch nicht überflüssig 😉

    Edit: Preisfrage: Würde das auf einer big Endian-Maschine funktionieren?



  • nwp2 schrieb:

    Edit: Preisfrage: Würde das auf einer big Endian-Maschine funktionieren?

    müsste eigentlich, aber machen würde ich's trotzdem nicht.
    🙂



  • Negative Zahlen wären auch nicht toll. Im übrigen hat sich bei memcmp(z1, z2, spaltenanzahl) noch ein kleiner Leichtsinnsfehler eingebaut, es werden so nur 5 Bytes verglichen.

    Ansonsten würde ich nicht sizeof(array)/sizeof(int) schreiben, sondern eher sizeof(array)/sizeof(*array) bzw. sizeof array / sizeof *array



  • Tim schrieb:

    Negative Zahlen wären auch nicht toll.

    ach ja, sogar mit char geht's nicht. memcmp funzt nur zuverlässig mit unsigned chars.
    🙂



  • Danke Leute 🙂 es funktioniert perfekt 😉
    lg Mike


Anmelden zum Antworten