Suchalgorithmen beantworten eine einfache Frage: Kommt ein bestimmter Wert in einer
Datenmenge vor, und wenn ja, an welcher Stelle? In Q1.2 werden die Daten zunächst als
Array oder als vergleichbare lineare Datenstruktur betrachtet. Ein Element ist über
seinen Index erreichbar, und ein Suchwert wird durch
Vergleiche mit gespeicherten Werten geprüft.
Lineare Suche: die naheliegende Grundstrategie
Die lineare Suche ist ein Suchalgorithmus, bei dem die Elemente einer Liste nacheinander
geprüft werden, bis der Suchwert gefunden wurde oder alle Elemente kontrolliert wurden.
Die Stärke der linearen Suche liegt darin, dass sie fast keine Voraussetzung an die
Daten stellt. Die Liste muss nicht sortiert sein, und es reicht, jedes Element
nacheinander erreichen zu können. Der Ablauf ist deshalb gut als erstes Suchverfahren
geeignet: Ein Index läuft von links nach rechts, jeder Schritt enthält genau einen
Vergleich, und der Ablauf endet entweder beim Treffer oder nach dem letzten Element.
Das folgende Struktogramm zeigt diese Ablaufstruktur ohne Java-Syntax: Initialisierung,
Wiederholung, Vergleich und die Entscheidung zwischen Treffer und Weitergehen werden
als Verfahrensschritte lesbar.
Im Java-Code werden dieselben Rollen wiedererkennbar: Der Index steuert die Position,
der Vergleich prüft den Suchwert, ein Treffer bricht den Ablauf ab und ein Nicht-Treffer
führt am Ende zur Rückgabe -1.
int linearSuche(int[] a, int suchwert) {
int i = 0;
while (i < a.length) {
if (a[i] == suchwert) return i;
i++;
}
return -1;
}
Ablaufbeispiel: a = [14, 3, 9, 27, 18, 5, 11], Suche nach 18
Der Suchwert 18 wird zuerst mit dem Wert an Index 0 verglichen,
danach mit Index 1, dann mit Index 2 und Index 3.
Erst an Index 4 entsteht ein Treffer. Wäre der Wert nicht enthalten,
müsste das Verfahren bis zum Ende weiterlaufen und anschließend -1 melden.
Für die Laufzeit bedeutet das qualitativ: Je mehr Elemente im Array liegen, desto mehr
Vergleiche können nötig werden. Im besten Fall steht der Suchwert direkt am Anfang.
Im ungünstigen Fall steht er ganz hinten oder kommt gar nicht vor. Die Zahl der möglichen
Vergleiche wächst dann ungefähr proportional zur Anzahl der Elemente.
Binäre Suche: Suche im sortierten Suchraum
Die binäre Suche ist ein Suchalgorithmus für
sortierte Daten.
Sie betrachtet in jedem Schritt die Mitte des aktuellen Suchraums und entscheidet
dadurch, welche Hälfte weiter untersucht werden muss.
Binäre Suche ist nicht einfach „die schnellere lineare Suche“. Sie ist eine andere
Strategie und benötigt eine zentrale Voraussetzung: Die Daten müssen sortiert sein.
Nur dann ist aus einem Vergleich mit dem mittleren Element ableitbar, ob der Suchwert
links oder rechts davon liegen kann. Ohne Sortierung könnte ein gesuchter Wert
fälschlich ausgeschlossen werden.
Der Suchraum ist der aktuell noch mögliche Bereich des Arrays. Zu Beginn
umfasst er das gesamte Array. Nach jedem Vergleich mit der Mitte bleibt nur noch die
linke oder rechte Hälfte übrig. Aus vielen einzelnen Prüfungen wird damit eine Folge
von Halbierungen.
Das Struktogramm macht sichtbar, wie die Steuerung über links,
rechts und mitte funktioniert. Entscheidend ist nicht die
Schreibweise, sondern die Frage, welcher Bereich nach jedem Vergleich noch möglich ist.
Die Halbierung des Suchraums folgt direkt aus den Entscheidungen: Ist der mittlere
Wert zu klein, verschiebt sich links hinter die Mitte; ist er zu groß,
rückt rechts vor die Mitte.
int binaereSuche(int[] a, int suchwert) {
int links = 0;
int rechts = a.length - 1;
while (links <= rechts) {
int mitte = (links + rechts) / 2;
if (a[mitte] == suchwert) return mitte;
if (a[mitte] < suchwert) links = mitte + 1;
else rechts = mitte - 1;
}
return -1;
}
Ablaufbeispiel: a = [3, 7, 11, 14, 18, 24, 31], Suche nach 24
Der Suchraum beginnt bei den Indizes 0..6. Die Mitte liegt bei Index
3, dort steht 14. Weil 24 größer ist, kann die
linke Hälfte nicht mehr relevant sein. Der neue Suchraum ist 4..6.
Die Mitte dieses Bereichs ist Index 5, dort steht 24.
Der Treffer entsteht nach zwei Vergleichen.
[0..6] → [4..6] → Treffer bei Index 5
Das Wachstum ist hier qualitativ logarithmisch: Wenn sich die Datenmenge verdoppelt,
kommt ungefähr nur ein weiterer Halbierungsschritt hinzu. Genau darin liegt die
besondere Effizienz der binären Suche. Zugleich zeigt sie bereits eine Denkbewegung,
die in Q1.3 wieder aufgegriffen wird:
Ein Problem wird durch Verkleinerung des Suchraums strukturiert. Die rekursive
Modellierung dieser Idee gehört aber in Q1.3.