web-dev-qa-db-de.com

Was ist der beste Sortieralgorithmus, um ein Array von kleinen Ganzzahlen zu sortieren?

Laut Frage-Titel, wenn das Array eine ungerade Länge hat und die Array-Elemente von 1 bis 10 nummeriert sind. 

Beispiel, 

3 6 8 1 3 7 7 9 4 1

Ich dachte an heapsort ? Da es sich um ein Array handelt, muss merge sort und insert sort verschoben werden und wäre nicht so effizient.

18
user236501

die Array-Elemente sind von 1 bis 10 nummeriert.

Mit dieser Einschränkung ist Zählsortierung weitaus effizienter als jeder allgemeine Sortieralgorithmus - es ist O (n)

31

Dies ist mein Zählsortierbeispiel

static int[] countingSort(int[] numbers) {
    int max = numbers[0];
    for (int i = 1; i < numbers.length; i++) {
        if (numbers[i] > max)
            max = numbers[i];
    }

    int[] sortedNumbers = new int[max+1];

    for (int i = 0; i < numbers.length; i++) {
        sortedNumbers[numbers[i]]++;
    }

    int insertPosition = 0;

    for (int i = 0; i <= max; i++) {
            for (int j = 0; j < sortedNumbers[i]; j++) {
                    numbers[insertPosition] = i;
                    insertPosition++;
            }
    }
    return numbers;
}
7
ben_muc

Bearbeiten: Eine Zählsortierung ist wahrscheinlich optimal, da die Elemente nur zwischen 1 und 10 liegen. Eine auf dieses Problem angewendete Zählsortierung wird in der Zeit O(n) ausgeführt. Eine Zusammenführungssortierung (wie ich unten empfohlen habe) wird nicht besser als O(nlogn) ausgeführt. Das Parallelisieren einer Zählsorte könnte interessant sein. Weisen Sie jedem Prozessor einfach ein Unterfeld mit n/p Elementen zu. Jeder Prozessor hätte sein eigenes Zählfeld der Größe 9. Dieser Schritt sollte O(n/p) Zeit beanspruchen. Konsolidieren Sie dann alle Zähl-Arrays in einem einzigen Array, was O(p) Zeit in Anspruch nehmen sollte. Ich habe den letzten Schritt in der Zählart, in der die Elemente in der Reihenfolge angeordnet sind, nicht vollständig durchdacht, aber es scheint, solange die Elemente des Zähl-Arrays atomar sind, Sie könnten jedem Einzelnen n/p-Abschnitte des ursprünglichen Arrays zuordnen Prozessoren und erreichen einige Parallelisierung. Bei einzelnen Elementen des Zählfelds würde es jedoch zu Konflikten kommen, wodurch die Parallelität möglicherweise erheblich reduziert wird. Sie können möglicherweise p-Prozessoren Unterabschnitte des count-Arrays zuweisen, und Sie befinden sich wieder in der Laufzeitumgebung O(n/p), wenn die Elemente ziemlich gleichmäßig verteilt sind, Sie wären jedoch auf 10 Prozessoren beschränkt. Wenn die Elemente nicht gleichmäßig verteilt sind, können ein oder mehrere Prozessoren einen größeren Teil der Arbeit erledigen. Das ist eine großartige Frage. Können Sie in O(n/p) eine Sortierung durchführen?

Quicksort ist ein hervorragender In-Place-Sortieralgorithmus, der schnell abläuft und Speicherplatz spart. Da die Elemente jedoch nur zwischen 1 und 10 liegen, erhalten Sie beim Sortieren einer großen Anzahl von Elementen anfangs oder zu Zwischenzeiten während der Sortierung große Läufe derselben Anzahl. In-Order-Arrays oder Sub-Arrays können die Leistung eines Quicksorts wirklich beeinträchtigen.

Wenn Sie sich nicht für das Gedächtnis interessieren, genügt ein einfacher Mergesort. Mergesort ist mit den schnellsten Standard-Sortieralgorithmen dabei. 

Die standardmäßige Collections.sort () - Implementierung in Java 7 ist ein Mergesort-Algorithmus, der von 'TimSort' angepasst wurde. Die standardmäßige Arrays.sort () - Implementierung in Java 7 ist ein Quicksort mit zwei Pivots.

Wenn Sie parallel arbeiten möchten, kann ein paralleler Quicksort auf großen Arrays mit einer geringen Anzahl von Prozessoren gute Ergebnisse erzielen, jedoch mit den gleichen Einschränkungen wie beim sequentiellen Quicksort. PSRS kann helfen, auf eine größere Anzahl von Prozessoren zu skalieren.

2
broadbear

Wenn es nur 10 Elemente gibt, lohnt es sich nicht, sich darüber Gedanken zu machen. Wenn es eine Million gibt, könnte es anfangen, bedeutsam zu werden.

2
user207421

Sie sollten dies für das Komplexitätsdiagramm betrachten Komplexitätsvergleichsdiagramm .

Der Vergleich des Sortieralgorithmus basiert auf dem Szenario „Bester, Durchschnittlicher, Worst-Case“ für Zeit- und Raumkomplexität. Basierend auf diesem Diagramm können Sie sehen, dass Counting Sort am besten aus Platz- und Zeitaufwand ist. Eine andere vergleichbare Methode ist Radix Sort.

Schlechteste [Zeit, Raum] -Komplexität von "Counting Sort": - [O (n + k), O (k)].

Schlechteste [Zeit, Raum] -Komplexität von "Radix Sort": - [O (nk), O (n + k)]. 

1
bibek koirala

QuickSort ist ein Divide and Conquer-Algorithmus. Er wählt ein Element als Drehpunkt aus und unterteilt das angegebene Array um den ausgewählten Drehpunkt und wiederholt dann den Vorgang. Es gibt viele verschiedene Versionen von quickSort, die Pivot auf unterschiedliche Weise auswählen

1
sdfahklj

Die Sortierreihenfolge ist in diesem Szenario am besten. 

Angenommen, die Daten sind Ganzzahlen in einem Bereich von 0-k. Erstellen Sie ein Array der Größe K, um zu verfolgen, wie viele Elemente angezeigt werden (3 Elemente mit dem Wert 0, 4 Elemente mit dem Wert 1 usw.). Bei dieser Zählung können Sie die Position eines Gegenstands bestimmen - alle 1er müssen hinter den 0er stehen, von denen es 3 gibt. Daher beginnen die 1er bei Punkt 4. So können wir die Artikel scannen und an ihrer richtigen Position einfügen.

Erstellen des Zählfeldes ist O (N) Das Einfügen von Elementen an ihrer richtigen Position ist O (N) Ich hier zu stark vereinfacht - es gibt eine Summierung der Zählungen und eine Sortierung, die die Sortierung aufrechterhält stabil.

0
Sai prateek

dies ist ein Beispiel für die einfache Sortierung (Insertion Sort).

private static void insertionSort(int[] a) {

    // [230, 23, 45, 34, 98]
    for (int j = 2; j < a.length; j++) {

        int key = a[j];
        int i = j - 1;

        while (i > 0 && a[i] > key) {
            a[i + 1] = a[i];
            i--;
        }
        a[i + 1] = key;
    }

    System.out.println("sorted array: " + Arrays.toString(a));
}
0
Yousuf Qureshi