Sortieren: Unterschied zwischen den Versionen
Marius (Diskussion | Beiträge) (→Heapsort) |
|||
Zeile 27: | Zeile 27: | ||
<source lang="java"> | <source lang="java"> | ||
+ | |||
public static void heapSort(int[] a) { | public static void heapSort(int[] a) { | ||
− | + | generateMaxHeap(a); | |
− | + | ||
− | + | for( int i = a.length - 1; i > 0; i--) { | |
− | + | tausche(a, 0, i); | |
− | + | heapify(a, 0, i-1); | |
− | } | + | } |
− | + | } | |
− | + | ||
− | + | private static void generateMaxHeap(int[] a) { | |
− | heapify(a, i, a.length); | + | for(int i = (a.length / 2); i >= 0; i--) { |
− | + | heapify(a, i, a.length-1); | |
− | } | + | } |
− | + | } | |
− | + | ||
− | + | ||
− | + | ||
− | + | private static void heapify(int[] a, int aktKnoten, int anzahlKnoten) { | |
− | + | ||
− | + | int lsNr = 2*aktKnoten+1, //Nummer des linken Sohns | |
− | + | rsNr = lsNr+1, //Nummer des rechten Sohns | |
− | tausche(a | + | selSohn; //Nummer des selektierten Sohns |
− | + | ||
− | + | if (lsNr <= anzahlKnoten && rsNr > anzahlKnoten) { //es gibt keinen rechten Sohn | |
− | + | if (a[lsNr] < a[aktKnoten]) { | |
− | + | tausche(a, lsNr, aktKnoten); | |
− | + | } | |
− | + | } | |
− | + | else { | |
− | + | if (rsNr <= anzahlKnoten) { | |
− | + | selSohn = (a[lsNr] < a[rsNr] ? lsNr : rsNr); | |
− | + | // Wähle den Sohn mit der kleineren Markierung aus. | |
− | + | // Bei Gleichheit wähle den rechten Sohn. | |
− | + | ||
− | } | + | if (a[selSohn] < a[aktKnoten]) { //Heap-Bedingung verletzt |
− | + | tausche(a, aktKnoten, selSohn); | |
− | + | heapify(a, selSohn, anzahlKnoten); | |
− | + | } | |
− | + | } | |
− | + | } | |
− | + | } | |
− | } | + | |
− | + | ||
+ | private static void tausche(int[] a, int i, int j){ | ||
+ | int swap = a[i]; | ||
+ | a[i] = a[j]; | ||
+ | a[j] = swap; | ||
+ | } | ||
</source> | </source> | ||
Version vom 8. Juni 2016, 16:58 Uhr
Das Sortieren ist ein Standardproblem der Informatik.
Inhaltsverzeichnis
Sortieralgoritmen
Bubblesort
Das Bubblesort-Sortierverfahren versucht in jeder Iteration das größte Element an das Ende des Feldes zu bewegen. Somit besteht das Ende des Feldes immer aus einem sortierten Teilfeld. Nach $n$ Durchläufen ist damit das Feld vollständig sortiert. Bei diesem Verfahren wird in jedem Schritt jedes Element mindestens ein Mal mit einem anderen verglichen.
bubbleSort(int[] A){ for(int n = A.length; n > 1; n--) { for (int i = 0; i < n-1; i++) { if (A[i] > A[i+1]){ int swap = A[i]; A[i] = A[i+1]; A[i+1] = swap; } } }
Heapsort
Im Heapsort wird sich die Eigenschaft zu Nutze gemacht, dass in einem korrekten Heap das kleinste Element immer in der Wurzel des Heaps steht. Wird dieses entfernt und im neuen Baum die Heapstruktur wiederhergestellt, lässt sich das Feld sortieren. Das Wiederherstellen eines Heaps geht relativ schnell.
public static void heapSort(int[] a) { generateMaxHeap(a); for( int i = a.length - 1; i > 0; i--) { tausche(a, 0, i); heapify(a, 0, i-1); } } private static void generateMaxHeap(int[] a) { for(int i = (a.length / 2); i >= 0; i--) { heapify(a, i, a.length-1); } } private static void heapify(int[] a, int aktKnoten, int anzahlKnoten) { int lsNr = 2*aktKnoten+1, //Nummer des linken Sohns rsNr = lsNr+1, //Nummer des rechten Sohns selSohn; //Nummer des selektierten Sohns if (lsNr <= anzahlKnoten && rsNr > anzahlKnoten) { //es gibt keinen rechten Sohn if (a[lsNr] < a[aktKnoten]) { tausche(a, lsNr, aktKnoten); } } else { if (rsNr <= anzahlKnoten) { selSohn = (a[lsNr] < a[rsNr] ? lsNr : rsNr); // Wähle den Sohn mit der kleineren Markierung aus. // Bei Gleichheit wähle den rechten Sohn. if (a[selSohn] < a[aktKnoten]) { //Heap-Bedingung verletzt tausche(a, aktKnoten, selSohn); heapify(a, selSohn, anzahlKnoten); } } } } private static void tausche(int[] a, int i, int j){ int swap = a[i]; a[i] = a[j]; a[j] = swap; }
Insertionsort
Beim Insertionsort (Einfügesortieren) wird versucht, ein Element in der passenden Stelle eines bereits sortierten Teilfeldes einzufügen und den Rest des Feldes dabei zu "verschieben". Da dieses Verfahren bei Feldern viel Aufwand während der Verschiebung erfordert, bieten sich Listen zur Implementierung hier besser an. Damit kann das Einfügen an eine gewisse Position viel einfacher erfolgen.
Insertionsort(int[] A) for (int i = 1; i < A.length; i++){ int insort = A[i]; int j = i; while (j > 1 && A[i-j] > insort){ A[j] = A[j-1]; j--; } A[j] = insort; }
Mergesort
Mergesort ist das klassische Beispiel eines Teile und herrsche-Algorithmus.
public static void sort(int[] a){ if( a.length > 1) { int mitte = arry.length / 2; int[] links = new int[mitte]; for (int i = 0; i <= links.length - 1; i++) { links[i] = a[i]; } int[] rechts = new int[a.length - mitte]; for (int i = mitte; i <= a.length - 1; i++) { rechts[i - mitte] = a[i]; } sort(links); sort(rechts); a = merge(links, rechts); } } public static int[] merge(int[] links, int[] rechts){ int[] ErgArray = new int[links.length + rechts.length]; int indexLinks = 0, indexRechts = 0, indexErg = 0; while (indexLinks < links.length && indexRechts < rechts.length) { if (links[indexLinks] < rechts[indexRechts]) { ErgArray[indexErg] = links[indexLinks]; indexLinks++; } else { ErgArray[indexErg] = rechts[indexRechts]; indexRechts++; } indexErg++; } while (indexLinks < links.length) { ErgArray[indexerg] = rechts[indexRechts]; indexRechts++; indexErg++; } while (indexRechts < rechts.length) { ErgArray[indexErg] = rechts[indexRechts]; indexRechts++; indexErg++; } return ErgArray; }
Quicksort
Quicksort ist das zweite übliche Beispiel für Teile und Herrsche-Sortieralgorithmen. In ihm wird anhand eines arbiträr (willkürlich) gewählten Wertes (meistens das mittlere) das Feld vorsortiert: Alle Elemente kleiner als das gewählte Element werden links davon einsortiert, alle größeren rechts davon. Damit hat man zwei Teilfelder, die selbst nicht sortiert sind. Also wird rekursiv nach demselben Muster vorgegangen: Die beiden kleineren Teilfelder werden wieder arbiträr nach einem Element aufgeteilt und in zwei grob sortierte Teilstrukturen aufgeteilt. Dies geschieht so lange, bis das Feld in Teilfelder der Größe 1 aufgeteilt wurde. Diese sind alle sortiert, somit auch die größeren Teilfelder und damit das ganze Feld.
public static void quicksort(int[] arr, int links, int rechts) { if (arr == null || arr.length == 0) { return; } if (links >= rechts) { return; } int mitte = links + (rechts - links) / 2; int pivot = arr[middle]; int i = links, j = rechts; while (i <= j) { while (arr[i] < pivot) { i++; } while (arr[j] > pivot) { j--; } if (i <= j) { int swap = arr[i]; arr[i] = arr[j]; arr[j] = swap; i++; j--; } } if (links < j){ quickSort(arr, low, j); } if (rechts > i){ quickSort(arr, i, rechts); } }