Sortieren eines Arrays in C?

Lesezeit: 7 Minuten

Benutzeravatar von Rajeev
Rajeev

Welches ist die beste Sortiertechnik, um das folgende Array zu sortieren, und wenn es Duplikate gibt, wie man damit umgeht:

int a= {1,3,6,7,1,2};

Und welches ist die beste Sortiertechnik von allen?

void BubbleSort(int a[], int array_size)
{
    int i, j, temp;
    for (i = 0; i < (array_size - 1); ++i)
    {
        for (j = 0; j < array_size - 1 - i; ++j )
        {
            if (a[j] > a[j+1])
            {
                temp = a[j+1];
                a[j+1] = a[j];
                a[j] = temp;
            }
        }
    }
}

  • Sehen: en.wikipedia.org/wiki/Sortieralgorithmus

    – Donotalo

    8. Oktober 2010 um 20:13 Uhr

  • Es gibt keine “beste Sortiertechnik von allen”, es hängt von der Größe Ihrer Daten ab und davon, ob sie zu Beginn einigermaßen sortiert sind. Ich würde dir empfehlen zu lesen de.wikipedia.org/wiki/… und den ganzen Wikipedia-Artikel auch.

    – schnaader

    8. Oktober 2010 um 20:13 Uhr

  • “Am besten” hängt von den Daten und anderen Einschränkungen ab: Speicher, Geschwindigkeit, wie falsch sortiert zu starten ist. Quicksort ist ein großartiger Kompromiss zwischen diesen. Bubble Sort ist das Beste für kleine Speicher. Was möchten Sie erreichen?

    – Kumpel

    8. Oktober 2010 um 20:16 Uhr

  • Die beste (wenn beste == schnellste) Sortiertechnik wäre, die Daten so zu erhalten, dass sie bereits sortiert sind.

    – Nik T

    8. Oktober 2010 um 20:17 Uhr

  • “folgendes Array” = “vorhergehendes Array”? Wenn ja, ist es am schnellsten, es sortiert aufzuschreiben. Im Ernst, ich mache das in generiertem Code.

    – Peter g.

    8. Oktober 2010 um 20:41 Uhr

Benutzeravatar von Alex Reece
Alex Reece

In C können Sie das eingebaute verwenden qsort Befehl:

int compare( const void* a, const void* b)
{
     int int_a = * ( (int*) a );
     int int_b = * ( (int*) b );

     if ( int_a == int_b ) return 0;
     else if ( int_a < int_b ) return -1;
     else return 1;
}

qsort( a, 6, sizeof(int), compare )

sehen: http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/


Um den zweiten Teil Ihrer Frage zu beantworten: Ein optimaler (vergleichsbasierter) Sortieralgorithmus ist einer, der mit O (n log (n)) Vergleichen ausgeführt wird. Es gibt mehrere, die diese Eigenschaft haben (einschließlich Schnellsortierung, Zusammenführungssortierung, Heap-Sortierung usw.), aber welche Sie verwenden sollten, hängt von Ihrem Anwendungsfall ab.

Als Randnotiz können Sie es manchmal besser machen als O(n log(n)), wenn Sie etwas über Ihre Daten wissen – siehe Wikipedia-Artikel auf Radix-Sortierung

  • @Alex: wenn du es schnell willst, stelle wenigstens eine ordentliche Vergleichsfunktion bereit! qsort braucht nicht, dass die zurückgegebenen Werte -1, 0, 1 sind, sondern “jede negative Zahl”, 0, “jede positive Zahl”, daher müssen Sie nur tun return *((int*)a)-*((int*)b); das ist viel schneller als Ihr Vorschlag.

    – kriss

    8. Oktober 2010 um 21:02 Uhr

  • @kriss: Ihr Vergleich ist im Falle eines Ganzzahlüberlaufs nicht genau definiert; daher sieht man oft Dinge wie return (a > b) - (a < b)

    – Christoph

    8. Oktober 2010 um 22:04 Uhr

  • @Stephen Canon: Einverstanden, Sie sollten Formeln wie die von Christoph verwenden, wenn Sie nichts über Ihren Datenbereich wissen und ein Überlauf auftreten kann. In der Praxis habe ich beim Umgang mit vorzeichenbehafteten Zahlen nie ein einziges Vorkommen gesehen, da ich keine ungefähre Vorstellung vom Datenbereich hatte (und meine Formeln sind auch für unsigned gut geeignet). Mein Punkt war hauptsächlich, dass der Ergebnistyp der Vergleichs-API nicht -1,0,1 ist (oder wir konnten strcmp nicht einmal zum Vergleichen von char* verwenden).

    – kriss

    9. Oktober 2010 um 2:34 Uhr


  • @kriss: Diese Verwendung der Notation ist einfach falsch. Auch wenn es randomisiert ist, es kann trifft Fälle, in denen es quadratische Zeit dauert. deshalb, die großes O ist quadratisch. Großes O stets meint schlimmsten Fall. Verwenden Sie unterschiedliche Notationen für lächerliche Komplexitätsschätzungen für “durchschnittliche Fälle”.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    9. Oktober 2010 um 9:45 Uhr


  • @kriss: Wenn ich sage, ein Algorithmus ist O(f(n)) in der Zeit, das heißt, die Zeit, die zum Laufen benötigt wird begrenzt durch ein konstantes Vielfaches von f(n)wobei die jeweilige Konstante implementierungsabhängig aber innerhalb einer Implementierung konstant ist, z alle möglichen Eingaben. Quicksort zu beanspruchen ist O(n log n) ist so absurd wie zu behaupten if (rand()==42) return find_prime_factors(n); else return NULL; ist O(1) in Gedenken an n.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    9. Oktober 2010 um 22:10 Uhr

Benutzeravatar von kriss
kriss

In Ihrem speziellen Fall ist die schnellste Sortierung wahrscheinlich die in dieser Antwort beschriebene. Es ist genau auf ein Array von 6 Ints optimiert und verwendet Sortiernetzwerke. es ist 20 mal (gemessen auf x86) schneller als Bibliothek qsort. Sortiernetzwerke sind optimal für Arrays mit fester Länge. Da es sich um eine feste Abfolge von Anweisungen handelt, können sie sogar einfach durch Hardware implementiert werden.

Im Allgemeinen gibt es viele Sortieralgorithmen, die für einen speziellen Fall optimiert sind. Die Allzweckalgorithmen wie Heap Sort oder Quick Sort sind für das Sortieren einer Reihe von Elementen an Ort und Stelle optimiert. Sie ergeben eine Komplexität von O(n.log(n)), wobei n die Anzahl der zu sortierenden Elemente ist.

Die Bibliotheksfunktion qsort() ist sehr gut codiert und effizient in Bezug auf die Komplexität, verwendet jedoch einen Aufruf einer vom Benutzer bereitgestellten Vergleichsfunktion, und dieser Aufruf hat ziemlich hohe Kosten.

Zum Sortieren sehr großer Datenmengen müssen sich Algorithmen auch um das Austauschen von Daten auf und von der Festplatte kümmern. Dies ist die Art der Sortierung, die in Datenbanken implementiert ist, und wenn Sie solche Anforderungen haben, ist es am besten, Daten in eine Datenbank zu stellen und zu verwenden Art eingebaut.

Benutzeravatar von haylem
Haylem

Beruht

Es hängt von verschiedenen Dingen ab. Aber im Allgemeinen Algorithmen mit a Teile und herrsche / dichotomisch Der Ansatz eignet sich gut für Sortierprobleme, da er interessante Komplexitäten für durchschnittliche Fälle aufweist.

Grundlagen

Um zu verstehen, welche Algorithmen am besten funktionieren, benötigen Sie Grundkenntnisse Komplexität der Algorithmen und Big-O-Notationdamit Sie verstehen können, wie sie in Bezug auf bewertet werden Durchschnittsszenarien, Best-Case- und Worst-Case-Szenarien. Darauf müssten Sie ggf. auch achten Stabilität des Sortieralgorithmus.

Ein effizienter Algorithmus ist zum Beispiel Quicksort. Wenn Sie Quicksort jedoch eine perfekt invertierte Liste geben, wird es schlecht funktionieren (eine einfache Auswahlsortierung wird in diesem Fall besser funktionieren!). Shell-Sort wäre normalerweise auch eine gute Ergänzung zu Quicksort, wenn Sie eine Voranalyse Ihrer Liste durchführen.

Sehen Sie sich das Folgende für “erweiterte Suchen” mit Teilen-und-Herrschen-Ansätzen an:

Und diese einfacheren Algorithmen für weniger komplexe:

Des Weiteren

Die oben genannten sind die üblichen Verdächtigen, wenn Sie anfangen, aber es gibt unzählige andere.

Wie von R. in den Kommentaren und von Kriss in seiner Antwort darauf hingewiesen, möchten Sie vielleicht einen Blick darauf werfen HeapSort, das theoretisch eine bessere Sortierkomplexität bietet als ein Quicksort (aber in der Praxis nicht oft besser abschneidet). Es gibt auch Varianten u hybride Algorithmen (z.B TimSort).

  • Wenn Sie Quicksort eine perfekt invertierte Liste zur Verfügung stellen, wird sie nur in der naivsten Implementierung degenerieren (nehmen Sie immer den Kopf der Liste als Pivot), und selbst dann ist es nicht schlimmer als BubbleSort. Auch das naive Quicksort würde mit einer bereits sortierten Liste schlecht abschneiden. Aber sehr einfache Änderungen am Algorithmus reichen aus, um das Problem zu umgehen (extrahieren Sie mehrere Zahlen aus der Liste als potenziellen Pivot und wählen Sie den Median als Pivot).

    – kriss

    8. Oktober 2010 um 20:56 Uhr


  • @kriss: Richtig. Aber das ist eine CS-Lernfrage, und deshalb spreche ich nur über die theoretische und grundlegende Umsetzung jedes dieser Ansätze. Natürlich können Sie Algorithmen optimieren und diese Nebenwirkungen minimieren, aber da das OP nach allgemeinen Sortierproblemen fragt, denke ich, dass es besser ist, diese Probleme zu lokalisieren.

    – Haylem

    8. Oktober 2010 um 23:33 Uhr

  • @haylem: Es ist in der Tat wahrscheinlich eine Lernfrage, aber das Risiko, über naive Implementierungen zu sprechen, besteht darin, dass der Leser glaubt, dass der Bibliotheksaufruf qsort eine naive Implementierung von QuickSort ist, was er nicht ist, und bei sortierten Datensätzen degenerieren würde. Wenn ich mich richtig erinnere, ist es in den meisten Implementierungen nicht einmal ein QuickSort.

    – kriss

    9. Oktober 2010 um 2:41 Uhr


  • Du hast ausgelassen Haufen sortierenwas wohl die ideale Sorte ist (O(1) Platz und O(n log n) Zeit).

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    9. Oktober 2010 um 3:24 Uhr

  • @R.: Ich habe viele von ihnen weggelassen, denke ich 🙂 Aber du hast recht, ich hätte heap-sort erwähnen sollen.

    – Haylem

    9. Oktober 2010 um 9:59 Uhr

Ich möchte einige Änderungen vornehmen: In C können Sie die eingebaute verwenden qsort Befehl:

int compare( const void* a, const void* b)
{
   int int_a = * ( (int*) a );
   int int_b = * ( (int*) b );

   // an easy expression for comparing
   return (int_a > int_b) - (int_a < int_b);
}

qsort( a, 6, sizeof(int), compare )

Die allerbeste Sortiertechnik hängt im Allgemeinen von der Größe eines Arrays ab. Merge Sort kann das Beste von allen sein, da es gemäß dem Big-O-Algorithmus eine bessere Raum- und Zeitkomplexität verwaltet (dies eignet sich besser für ein großes Array).

1395820cookie-checkSortieren eines Arrays in C?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy