Wie Karten auf der Hand
Wer Spielkarten aufnimmt, steckt jede neue Karte sofort an die passende Stelle zwischen die schon geordneten. Genau so arbeitet Insertionsort (Sortieren durch Einfügen).
- Start:das erste Element allein ist schon ein sortierter Teil.
- Eine Runde:das erste Element des unsortierten Teils wird in einem Zwischenspeicher
xgemerkt. - Verschieben:von rechts nach links rückt jedes Element des sortierten Teils, das größer als
xist, einen Platz nach rechts. - Einfügen:trifft der Vergleich auf ein Element \(\le x\) oder auf den Anfang, kommt
xin die entstandene Lücke.
| i | x | rücken nach rechts | Vergleiche | hand danach |
|---|---|---|---|---|
| 1 | 4 | 9 | 1 | 4 9 | 7 2 8 |
| 2 | 7 | 9 | 2 | 4 7 9 | 2 8 |
| 3 | 2 | 9, 7, 4 | 3 | 2 4 7 9 | 8 |
| 4 | 8 | 9 | 2 | 2 4 7 8 9 |
- Verschieben statt Tauschen:jedes größere Element wird nur einmal kopiert;
xwird erst ganz am Ende geschrieben.
Ziehe die angehobene Karte mit Maus oder Finger an ihren Platz im sortierten Teil (oder verschiebe sie mit ←/→) und prüfe mit Enter. Probiere danach „Vorsortiert“ und „Umgekehrt“.
Halte fest: Eine Karte wandert nur so weit nach links, wie links von ihr größere Karten liegen — liegt sie schon richtig, kostet sie einen einzigen Vergleich.
Algorithmus und Aufwand
Die äußere Schleife holt das nächste Element, die innere while-Schleife schiebt mit dem Index j nach links.
public static void insertionSort(int[] a) {
for (int i = 1; i < a.length; i++) {
int x = a[i]; // Zwischenspeicher
int j = i - 1;
while (j >= 0 && a[j] > x) {
a[j + 1] = a[j]; // größeres Element rückt nach rechts
j--;
}
a[j + 1] = x; // in die Lücke einfügen
}
}
- Reihenfolge:erst
j >= 0prüfen, danna[j]lesen — sonst droht beij = -1eineArrayIndexOutOfBoundsException. - Bester Fall:vorsortiert — jedes Element braucht genau einen Vergleich und keine Verschiebung: \(n-1\) Vergleiche.
- Ungünstigster Fall:umgekehrt sortiert — das Element mit Index \(i\) wandert ganz nach vorn: \(i\) Vergleiche und \(i\) Verschiebungen.
- Stabil:wegen
a[j] > x(nicht>=) stopptxhinter einem gleich großen Element — gleiche Werte behalten ihre Reihenfolge.
Insertionsort: vorsortiert \(n-1\) Vergleiche, umgekehrt sortiert \(\dfrac{n(n-1)}{2}\) Vergleiche — stabil.
Allgemeine Hinweise
Zwischenspeicher zuerst
Ohne x = a[i] überschreibt die erste Verschiebung a[i] — das einzufügende Element wäre verloren.
Fast sortiert? Insertionsort!
Liegen nur wenige Elemente falsch, bleibt der Aufwand nahe bei \(n-1\) Vergleichen. Selectionsort vergleicht dagegen immer \(\frac{n(n-1)}{2}\)-mal.
Einfügen nach der Schleife
Die Zuweisung a[j + 1] = x; gehört hinter die while-Schleife. Innerhalb der Schleife würde x bei jedem Schritt geschrieben.
