Sortieren: Unterschied zwischen den Versionen

Aus EINI
Wechseln zu: Navigation, Suche
(Quicksort)
(Insertionsort)
Zeile 73: Zeile 73:
  
 
==Insertionsort==
 
==Insertionsort==
 +
 +
Beim Insertionsort (Einfügesortieren) wird versucht, ein Element an die passende 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 Veschiebung erfordert, bieten sich Listen zur Implementierung hier besser an, da das Einfügen an eine gewisse Position viel einfacher erfolgen kann.
  
 
<source lang="java">
 
<source lang="java">

Version vom 9. März 2016, 13:03 Uhr

Das Sortieren ist ein Standardproblem der Informatik

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 insbesondere vollständig sortiert. Jedoch wird bei diesem Verfahren 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 dabei relativ schnell.

public static void heapSort(int[] a) {
       generateMaxHeap(a);
       for( int i = a.length - 1; i > 0; i--) {
           tausche(a, i, 0);
           heapify(a, 0, i);
       }
}

public static void generateMaxHeap(int[] a) {
       for(int i = (a.length / 2) - 1; i >= 0; i--) {
          heapify(a, i, a.length);
       }
}

public staitc void heapify(int[] a, int k, int anzahlKnoten) {
       int lsNR = 2*k,    //Nummer des linken Sohns
           rsNR = 2*k+1,  //Nummer des rechten Sohns
           selSohn;       //Nummer des selektierten Sohns

       if (lsNr <= anzahlKnoten && rsNr > anzahlKnoten) { //es gibt keinen rechten Sohn
           if (heapFeld[lsNr] < heapFeld[k] {
               tausche(a, k, lsNr);
           }
       }
       else if (rsNr <= anzahlKnoten) {
            selSohn = (heapFeld[lsNr] < heapFeld[rsNr] ? lsNr : rsNr);
            // Wähle den Sohn mit der kleineren Markierung aus.
            // Bei Gleichheit wähle den rechten Sohn.

            if (heapFeld[selSohn] < heapFeld[k]) {  //Heap-Bedingung verletzt
                tausche(a, k, selSohn);
                heapify(a, selSohn, anzahlKnoten);
            }
       }
}


public 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 an die passende 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 Veschiebung erfordert, bieten sich Listen zur Implementierung hier besser an, da das Einfügen an eine gewisse Position viel einfacher erfolgen kann.

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ößer rechts davon. Damit hat man zwei Teilfelder, die selbst nicht sortiert sind, aber wenn sie sortiert wären, wäre auch das Gesamtfeld sortiert. Also geht man rekursiv nach dem selben Muster vor. 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 jedoch alle sortiert, also auch die größeren Teilfelder, also 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);
       }
}