🔢 Bubble Sort, Quick Sort, Heap Sort, Selection Sort und Merge Sort einfach erklärt🚀

Beim Sortieren von Daten gibt es viele Wege zum Ziel – einige schnell, andere langsam, manche elegant, andere eher simpel. In diesem Artikel werden Bubble Sort, Quick Sort, Heap Sort, Selection Sort und Merge Sort einfach und anschaulich erklärt.

🫧 1. Bubble Sort

📖 Theorie:

Bubble Sort vergleicht jedes benachbarte Element und tauscht sie, wenn sie in der falschen Reihenfolge sind. Das größte Element „wandert“ bei jedem Durchgang nach oben, wie eine Blase. Dieser Vorgang wird so lange wiederholt, bis das gesamte Array sortiert ist.

💻 Beispielcode:

def bubble_sort(arr):
    n = len(arr)
    # Äußere Schleife für jeden Durchgang
    for i in range(n):
        # Innere Schleife für den Vergleich benachbarter Elemente
        for j in range(0, n - i - 1):
            # Wenn das linke Element größer ist, tausche die beiden
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr

# Beispiel
zahlen = [5, 3, 8, 4, 2]
print(bubble_sort(zahlen))  # Ausgabe: [2, 3, 4, 5, 8]

⏱️ Laufzeit:

  • Durchschnitt: O(n²)
  • Schlechtester Fall: O(n²)
  • Bester Fall: O(n) (wenn das Array schon sortiert ist)

⚡ 2. Quick Sort

📖 Theorie:

Quick Sort ist ein sogenannter „Teile-und-herrsche“-Algorithmus. Das große Problem (unsortierte Liste) wird immer wieder in kleinere Teilprobleme zerlegt, bis diese einfach zu lösen sind.

Quick Sort ist dabei besonders schnell und effizient und wird in vielen Programmiersprachen standardmäßig verwendet.

🎯 Wie funktioniert Quick Sort Schritt für Schritt?

  1. 📌 Pivot auswählen
  2. 🪄 Liste in kleinere und größere Elemente aufteilen
  3. 🔁 Rekursiv sortieren
  4. 🛠️ Zusammenfügen

👉 Beispiel:
Liste: [5, 3, 8, 4, 2] → Pivot = 5
Links: [3, 4, 2] | Pivot: 5 | Rechts: [8]

💻 Beispielcode:

import random

def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    else:
        pivot = random.choice(arr)
        kleiner = [x for x in arr if x < pivot]
        gleich = [x for x in arr if x == pivot]
        größer = [x for x in arr if x > pivot]
        return quick_sort(kleiner) + gleich + quick_sort(größer)

# Beispiel
zahlen = [5, 3, 8, 4, 2]
print(quick_sort(zahlen))  # Ausgabe: [2, 3, 4, 5, 8]

⏱️ Laufzeit:

  • Durchschnitt: O(n log n)
  • Schlechtester Fall: O(n²) (bei schlechter Pivot-Wahl)
  • Bester Fall: O(n log n)

🏗️ 3. Heap Sort

📖 Theorie:

Heap Sort nutzt eine spezielle Datenstruktur – den Heap. Ein Heap ist ein Baum, bei dem jedes Elternelement größer (Max-Heap) oder kleiner (Min-Heap) als seine Kindknoten ist. Ziel ist es, das größte Element schnell an den Anfang (bzw. das Ende) des Arrays zu bringen.

🎯 Wie funktioniert Heap Sort Schritt für Schritt?

  1. Heap bauen:
    Die Liste wird in einen Max-Heap umgewandelt. Das größte Element steht dann ganz oben.
  2. Größtes Element entfernen:
    Das oberste Element wird ans Ende des Arrays getauscht.
  3. Heap verkleinern:
    Die Größe des Heaps wird reduziert und die Struktur wiederhergestellt (Heapify).
  4. Wiederholen:
    Dies wird solange wiederholt, bis der Heap leer ist.

💻 Beispielcode:

def heapify(arr, n, i):
    largest = i
    left = 2 * i + 1
    right = 2 * i + 2

    # Prüfen, ob linkes Kind größer ist
    if left < n and arr[left] > arr[largest]:
        largest = left

    # Prüfen, ob rechtes Kind größer ist
    if right < n and arr[right] > arr[largest]:
        largest = right

    # Wenn das größte Element nicht an Position i ist, tauschen und weiter heapify
    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]
        heapify(arr, n, largest)

def heap_sort(arr):
    n = len(arr)

    # Max-Heap bauen
    for i in range(n // 2 - 1, -1, -1):
        heapify(arr, n, i)

    # Elemente aus dem Heap sortieren
    for i in range(n - 1, 0, -1):
        arr[i], arr[0] = arr[0], arr[i]  # Größtes Element ans Ende tauschen
        heapify(arr, i, 0)

    return arr

# Beispiel
zahlen = [5, 3, 8, 4, 2]
print(heap_sort(zahlen))  # Ausgabe: [2, 3, 4, 5, 8]

⏱️ Laufzeit:

  • Durchschnitt: O(n log n)
  • Schlechtester Fall: O(n log n)
  • Bester Fall: O(n log n)

🎯 4. Selection Sort

📖 Theorie:

Selection Sort sucht in jedem Durchgang das kleinste Element im unsortierten Teil des Arrays und tauscht es an die richtige Stelle nach vorne.

🎯 Wie funktioniert Selection Sort Schritt für Schritt?

  1. Das kleinste Element im gesamten Array suchen.
  2. Mit dem ersten Element tauschen.
  3. Das kleinste Element im restlichen (unsortierten) Teil suchen.
  4. Mit dem nächsten Element tauschen.
  5. Solange wiederholen, bis das Array sortiert ist.

👉 Selection Sort ist einfach, aber leider ineffizient bei großen Datenmengen.

💻 Beispielcode:

def selection_sort(arr):
    n = len(arr)
    for i in range(n):
        min_index = i
        for j in range(i + 1, n):
            if arr[j] < arr[min_index]:
                min_index = j
        arr[i], arr[min_index] = arr[min_index], arr[i]
    return arr

# Beispiel
zahlen = [5, 3, 8, 4, 2]
print(selection_sort(zahlen))  # Ausgabe: [2, 3, 4, 5, 8]

⏱️ Laufzeit:

  • Durchschnitt: O(n²)
  • Schlechtester Fall: O(n²)
  • Bester Fall: O(n²)

🛠️ 5. Merge Sort

📖 Theorie:

Merge Sort ist ebenfalls ein „Teile-und-herrsche“-Algorithmus, ähnlich wie Quick Sort, aber garantiert immer eine gute Laufzeit.

🎯 Wie funktioniert Merge Sort Schritt für Schritt?

  1. Die Liste wird in zwei Hälften geteilt.
  2. Jede Hälfte wird rekursiv sortiert.
  3. Die beiden sortierten Hälften werden zusammengeführt (Merge).

👉 Der Vorteil: Die Teilung ist immer gleichmäßig, was die Laufzeit stabil hält.

💻 Beispielcode:

def merge_sort(arr):
    if len(arr) <= 1:
        return arr

    mid = len(arr) // 2
    left = merge_sort(arr[:mid])
    right = merge_sort(arr[mid:])

    return merge(left, right)

def merge(left, right):
    result = []
    i = j = 0

    # Elemente der beiden Listen zusammenführen
    while i < len(left) and j < len(right):
        if left[i] < right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1

    # Restliche Elemente anhängen
    result.extend(left[i:])
    result.extend(right[j:])
    return result

# Beispiel
zahlen = [5, 3, 8, 4, 2]
print(merge_sort(zahlen))  # Ausgabe: [2, 3, 4, 5, 8]

⏱️ Laufzeit:

  • Durchschnitt: O(n log n)
  • Schlechtester Fall: O(n log n)
  • Bester Fall: O(n log n)

📚 Fazit: Sortieralgorithmen im Vergleich

KriteriumBubble SortQuick SortHeap SortSelection SortMerge Sort
GeschwindigkeitLangsamSehr schnellSchnellLangsamSchnell
Durchschnitts-LaufzeitO(n²)O(n log n)O(n log n)O(n²)O(n log n)
SpeicherbedarfGeringGeringGeringGeringHoch (zusätzlicher Speicher wird benötigt)
ArbeitsweiseVergleichen & TauschenPivot wählen & aufteilenHeap-DatenstrukturKleinstes Element findenTeilen & Zusammenfügen
Worst-CaseO(n²)O(n²)O(n log n)O(n²)O(n log n)

💡 Zusammenfassung:

  • Bubble Sort: Einfach zu verstehen, aber ineffizient.
  • Quick Sort: Sehr effizient, wenn das Pivot gut gewählt wird.
  • Heap Sort: Stabil und speichereffizient.
  • Selection Sort: Einfach, aber nicht empfehlenswert für große Datenmengen.
  • Merge Sort: Sehr zuverlässig mit stabiler Laufzeit, braucht aber zusätzlichen Speicher.

Wenn du große Datenmengen sortieren möchtest, sind Quick Sort, Heap Sort oder Merge Sort die besten Optionen. Bubble Sort und Selection Sort sind eher für Lernzwecke geeignet.