C-Bibliotheksfunktion zum Sortieren

96

Gibt es in der C-Standardbibliothek eine Bibliotheksfunktion zum Sortieren?

Ankur
quelle
21
@Alexandru, der ganze Sinn der SO ist ein Ort für seine alle Programmierbezogene Frage, von jeder Spielstärke. Wo sollte Google die Nutzer Ihrer Meinung nach anleiten, wenn sie Ihre Abfrage verwenden? Die Mächte, die es wollen, kommen hierher - wenn SO der oberste Google-Link für diese Abfrage ist, ist unsere Arbeit erledigt.
Paxdiablo
1
Mein ursprünglicher Code war faul und wahrscheinlich ganz anders als bei einer Google-Suche. Nach all den Community-Eingaben haben Sie jedoch ein Beispiel für eine gute Implementierung der Verwendung von qsort.
Wiederholen Sie
@paxdiablo: Wenn dies der Fall ist, können sie genauso gut einfach die Standard-lib-Dokumentation hosten - ich bezweifle, dass diese Frage hier etwas über diese kanonische Referenz hinaus hinzufügen wird. Für einige komplexe Fälle vielleicht - aber nur um eine Grundfunktion zu finden?
Eamon Nerbonne
4
Selbst Fragen wie diese tragen zur vollständigen Vollständigkeit von SO als hilfreiche Datenbank für feststeckende Codierer bei.
Thomaspaulb
7
In vielen Fällen wissen die Leute auch nicht, wonach sie suchen sollen. Wenn Sie wissen, dass c eine Sortierfunktion namens qsort () hat, ist die Dokumentation leicht zugänglich. Wenn Sie jedoch nicht wissen, wonach Sie suchen sollen, welche Ressource Sie verwenden sollen.
Wiederholung

Antworten:

119

qsort()ist die Funktion, die Sie suchen. Sie rufen es mit einem Zeiger auf Ihr Datenarray, der Anzahl der Elemente in diesem Array, der Größe jedes Elements und einer Vergleichsfunktion auf.

Es macht seine Magie und Ihr Array ist an Ort und Stelle sortiert. Ein Beispiel folgt:

#include <stdio.h>
#include <stdlib.h>
int comp (const void * elem1, const void * elem2) 
{
    int f = *((int*)elem1);
    int s = *((int*)elem2);
    if (f > s) return  1;
    if (f < s) return -1;
    return 0;
}
int main(int argc, char* argv[]) 
{
    int x[] = {4,5,2,3,1,0,9,8,6,7};

    qsort (x, sizeof(x)/sizeof(*x), sizeof(*x), comp);

    for (int i = 0 ; i < 10 ; i++)
        printf ("%d ", x[i]);

    return 0;
}
Wiederholung
quelle
3
Sie sollten wirklich sizeof (* x) verwenden, falls Sie den Typ in Zukunft jemals ändern sollten, aber +1, um ein Beispiel bereitzustellen.
Paxdiablo
12
Im Allgemeinen führt ein Versuch, Ints durch Subtrahieren voneinander zu vergleichen, zu einem Überlauf. Es ist besser, sich von Anfang an von dieser schlechten Angewohnheit fernzuhalten. Verwenden Siereturn (f > s) - (f < s);
AnT
4
Okay, geändert gemäß den meisten Vorschlägen. Ich ziehe die Grenze, @ChrisL, wenn ich size_t benötige, da meine Arrays nie so groß werden :-) Und @AndreyT, obwohl dieser Hack klug ist, bevorzuge ich, dass mein Code lesbar ist :-)
paxdiablo
2
@paxdiablo: Dieser "Hack" ist eine etablierte Redewendung. Jeder Programmierer, der sein Salz wert ist, erkennt es sofort. Es hat keine negativen Auswirkungen auf die Lesbarkeit.
AnT
2
@JAamish ISO C99 Standard N1256, in "7.20.5.2 Die qsortFunktion" Punkt 4 "Wenn zwei Elemente als gleich verglichen werden, ist ihre Reihenfolge im resultierenden sortierten Array nicht angegeben."
12431234123412341234123
60

Die C / C ++ - Standardbibliothek <stdlib.h>enthält qsortFunktionen.

Dies ist nicht die beste schnelle Sortierimplementierung der Welt, aber sie ist schnell genug und SEHR EINFACH zu verwenden ... die formale Syntax von qsort lautet:

qsort(<arrayname>,<size>,sizeof(<elementsize>),compare_function);

Das einzige, was Sie implementieren müssen, ist die compare_function, die zwei Argumente vom Typ "const void" akzeptiert, die in die entsprechende Datenstruktur umgewandelt werden können, und dann einen dieser drei Werte zurückgibt:

  • negativ, wenn a vor b sein sollte
  • 0, wenn a gleich b ist
  • positiv, wenn a nach b sein sollte

1. Vergleichen einer Liste von ganzen Zahlen :

einfach gegossen , wenn a und b auf ganze Zahlen x < y, x-ynegativ ist , x == y, x-y = 0, x > y, x-ypositiv ist x-yeine Abkürzung , wie es :) zu umkehren zu tun ist , *x - *yum *y - *xin abnehmenden / umgekehrte Reihenfolge zum Sortieren

int compare_function(const void *a,const void *b) {
int *x = (int *) a;
int *y = (int *) b;
return *x - *y;
}

2. Vergleichen einer Liste von Zeichenfolgen :

Zum Vergleichen von Zeichenfolgen benötigen Sie strcmpFunktionen in <string.h>lib. strcmpwird standardmäßig -ve, 0, ve entsprechend zurückgeben ... um in umgekehrter Reihenfolge zu sortieren, kehren Sie einfach das von strcmp zurückgegebene Vorzeichen um

#include <string.h>
int compare_function(const void *a,const void *b) {
return (strcmp((char *)a,(char *)b));
}

3. Vergleichen von Gleitkommazahlen :

int compare_function(const void *a,const void *b) {
double *x = (double *) a;
double *y = (double *) b;
// return *x - *y; // this is WRONG...
if (*x < *y) return -1;
else if (*x > *y) return 1; return 0;
}

4. Vergleichen von Datensätzen anhand eines Schlüssels :

Manchmal müssen Sie komplexere Dinge sortieren, z. B. Aufzeichnungen. Hier ist der einfachste Weg, dies mit der qsortBibliothek zu tun .

typedef struct {
int key;
double value;
} the_record;

int compare_function(const void *a,const void *b) {
the_record *x = (the_record *) a;
the_record *y = (the_record *) b;
return x->key - y->key;
}
whacko__Cracko
quelle
2
Eine ziemlich gute Antwort, aber die Erklärung des Rückgabewerts der Vergleichsfunktion ist rückwärts. In einigen Beispielen führen Sie außerdem den xy-Trick aus, der zu fehlerhaften Ergebnissen führen kann (und weniger offensichtlich ist als ein einfacher Vergleich).
Adrian McCarthy
Nun, soweit es mich betrifft, funktioniert dies für jeden Wettbewerb;)
whacko__Cracko
5
Der xy-Trick funktioniert nicht, wenn der Unterschied zwischen x und y größer ist als der größte darstellbare int. Es ist also in Ordnung, wenn zwei positive Zahlen verglichen werden, aber der Vergleich, z. B. INT_MAX und -10, schlägt fehl. Upvoted, weil ich alle Beispiele für das Sortieren sehr unterschiedlicher Typen mag.
Douglas
2
Neben dem Überlaufproblem sowohl in der Ganzzahlkomparator- als auch in der Schlüsselkomparatorfunktion ist die Zeichenfolgenvergleichsfunktion falsch. Beim Sortieren eines Arrays von intwerden die an den Komparator übergebenen Werte beide int *als getarnt void *. Beim Sortieren eines Arrays von char *werden daher die an den Komparator übergebenen Werte beide char **als getarnt void *. Daher muss der richtige Code sein : int compare_function(const void *a,const void *b) { return (strcmp(*(char **)a, *(char **)b)); }.
Jonathan Leffler
1
Berücksichtigen if (x > y) return +1; else if (x < y) return -1; else return 0;Sie für überlaufsichere Ganzzahlvergleiche , oder wenn Sie einen einfachen Ausdruck wünschen, dann return (x > y) - (x < y);. Dies wertet immer zwei Vergleiche auf C-Ebene aus, aber der Optimierer kann dies möglicherweise vermeiden. Die Subtraktion funktioniert nicht bei vorzeichenlosen Werten. Die erste Version funktioniert gut, wenn Sie sich mit einer Reihe von Vergleichen befassen - indem Sie zuerst zwei ganzzahlige Elemente einer Struktur vergleichen und wenn sie gleich sind, dann zwei Doppelelemente, dann zwei Zeichenfolgen usw. Es gibt mehr als einen Weg, dies zu tun. in C sowie Perl.
Jonathan Leffler
9

Sicher: qsort()ist eine Implementierung einer Art (nicht unbedingt Quicksort, wie der Name vermuten lässt).

Probieren Sie man 3 qsort aus oder lesen Sie es unter http://linux.die.net/man/3/qsort

McPherrinM
quelle
7
qsortmuss nicht mit Quicksort implementiert werden.
James McNellis
6

Https://github.com/swenson/sort ist zwar nicht genau in der Standardbibliothek enthalten, verfügt jedoch nur über zwei Header-Dateien, die Sie einschließen können, um Zugriff auf eine Vielzahl unglaublich schneller Sortierroutings zu erhalten, z.

#define SORT_NAME int64 #define SORT_TYPE int64_t #define SORT_CMP ( x , y ) (( x ) - ( y )) #include "sort.h" / * Sie haben jetzt Zugriff auf int64_quick_sort, int64_tim_sort usw., z. B. * / 
int64_quick_sort ( arr , 128 ); / * Angenommen, Sie haben int * arr oder int arr [128]; * /

   
 
  

Dies sollte mindestens doppelt so schnell sein wie die Standardbibliothek qsort , da keine Funktionszeiger verwendet werden und viele andere Sortieralgorithmusoptionen zur Auswahl stehen.

Es ist in C89, sollte also in praktisch jedem C-Compiler funktionieren.

Christopher Swenson
quelle
4

versuchen Sie es qsortin stdlib.h.

Travelling Tech Guy
quelle
4

Verwenden Sie qsort()in <stdlib.h>.

@paxdiablo Die qsort()Funktion entspricht ISO / IEC 9899: 1990 ("ISO C90").

Primzahl
quelle
3

Es stehen mehrere C-Sortierfunktionen zur Verfügung stdlib.h. Sie können man 3 qsortauf einem Unix-Computer eine Liste erstellen, die jedoch Folgendes enthält:

  • Heapsort
  • schnelle Sorte
  • Zusammenführen, sortieren
dj2
quelle
7
Heapsort und Mergesort sind nicht im Standard.
Technowise
3
Weder ist Quicksort. Der Standard schreibt nicht vor, welcher Algorithmus verwendet wird.
Paxdiablo