Home > Informatik > Stufe Q1 > 12. Suchverfahren

12.2 Binäre Suche

Überblick - Lineare Suche - Binäre Suche - Binäre Suchbäume - Index- u. Interpolationssuche

Die binäre Suche

Wenn die zu durchsuchenden Daten sortiert sind, kann man ein sehr viel effizienteres Suchverfahren anwenden als die lineare bzw. sequentielle Suche, nämlich die binäre Suche.

Die binäre Suche erfolgt nach dem Prinzip "Teile und herrsche". Das heißt, man teilt die zu durchsuchenden Daten in zwei Hälften und ermittelt dann, in welcher Hälfte das zu suchende Element vorkommt. Die andere Hälfte kann ignoriert werden. So wird bereits in dem ersten Suchschritt die Menge der zu durchsuchenden Daten um 50% reduziert.

Stellen Sie sich vor, Sie stehen vor einem Bücherregal, und die Bücher sind nach Autoren aufsteigend alphabetisch sortiert. Sie suchen nun nach einem Buch des Autoren Max Frisch, weil Sie das gerade im Deutsch-Kurs behandeln. Sie beginnen Ihre Suche in der Mitte des Regals, wo mit hoher Wahrscheinlichkeitkeit Autoren wie Klaus Mann oder Karl May stehen. Sofort erkennen Sie: Max Frisch muss in der linken Hälfte untergebracht sein. Die rechte Hälfte des Regals können Sie ignorieren, Sie haben also die zu durchsuchende Datenmenge um 50% reduziert.

Nun stellen Sie sich ungefähr in der Mitte der linken Hälfte auf und schauen, welche Autoren dort vorkommen. Die Autoren fangen alle mit 'E' an. Max Frisch muss sich also in der rechten Hälfte der linken Hälfte befinden. Sie gehen zur Mitte dieses Viertels und machen genau so weiter, bis Sie schließlich ihren Max Frisch gefunden haben, oder bis sie festgestellt haben, dass sie das Buch wohl verliehen oder wo anders hingelegt haben.

Eine halb-quantitative Einschätzung der Suchzeit

Wir suchen die Zahl 16 in einem sortierten Array:

1 3 4 6 7 9 12 14 15 16 18 21 22 25 26 32 35 37 38 40 42 50 56 58 59 61 75 76 79 81 83 92

Zunächst teilen wir den Array in zwei Hälften mit je 16 Elementen

1 3 4 6 7 9 12 14 15 16 18 21 22 25 26 32 35 37 38 40 42 50 56 58 59 61 75 76 79 81 83 92

Die größte Zahl der linken Hälfte ist größer als die Suchzahl 16, also machen wir in der linken Hälfte weiter und ignorieren die rechte Hälfte.

Die linke Hälfte wird jetzt wieder in zwei Hälften unterteilt:

1 3 4 6 7 9 12 14 15 16 18 21 22 25 26 32 35 37 38 40 42 50 56 58 59 61 75 76 79 81 83 92

Die größte Zahl in der linken Hälfte ist kleiner als die Suchzahl 16, daher machen wir in der gelb markierten rechten Hälfte des Teilarrays weiter. Diese unterteilen wir wieder in zwei Hälften:

1 3 4 6 7 9 12 14 15 16 18 21 22 25 26 32 35 37 38 40 42 50 56 58 59 61 75 76 79 81 83 92

Die größte Zahl der linken Hälfte ist größer als die Suchzahl 16, also machen wir in der linken Hälfte weiter und ignorieren die rechte Hälfte.

1 3 4 6 7 9 12 14 15 16 18 21 22 25 26 32 35 37 38 40 42 50 56 58 59 61 75 76 79 81 83 92

Die größte Zahl der linken Hälfte stimmt mit der Suchzahl überein, also können wir das Suchen mit Erfolg beenden.

Einschätzung der Suchzeit
  • Der Array hat 32 Elemente (Index 0..31).
  • Der Index der größten Zahl der linken Hälfte ist dann 15 (Rechenoperation 1).
  • Wir vergleichen diese Zahl (32) mit der Suchzahl (16) (Rechenoperation 2).
  • Der Index der größten Zahl der linken Hälfte ist dann 7 (Rechenoperation 3).
  • Wir vergleichen diese Zahl (14) mit der Suchzahl (16) (Rechenoperation 4).
  • Der Index der größten Zahl der linken Hälfte ist dann 11 (Rechenoperation 5).
  • Wir vergleichen diese Zahl (21) mit der Suchzahl (16) (Rechenoperation 6).
  • Der Index der größten Zahl der linken Hälfte ist dann 9 (Rechenoperation 7).
  • Wir vergleichen diese Zahl (16) mit der Suchzahl (16) (Rechenoperation 8).

Wir benötigen also acht Rechenoperationen, um die Suchzahl in dem Array zu finden, davon waren vier Operationen logische Vergleiche, und vier Operationen dienten zur Berechnung der Grenzen der jeweiligen Hälften.

Hätten wir die Suchzahl in einer unsortierten Liste der Größe 32 gesucht, hätten wir im Schnitt 16 Vergleiche benötigt (N/2), also doppelt so viel (mindestens).

Vergleichen wir einmal Worst Case- und Best Case-Szenarien für die beiden Suchverfahren und berücksichtigen dabei nur die Vergleichsoperationen.

Lineare Suche:

Best Case = 1 Rechenoperationen,

Worst Case = 32 Rechenoperationen (32 Vergleiche)

Binäre Suche:

Best Case = 2 Rechenoperationen,

Worst Case = 10 Rechenoperationen (5 Vergleiche, 5 Berechnungen)

Eine quantitative Einschätzung der Suchzeit

Bei der binären Suche wird die Anzahl der zu durchsuchenden Elemente bei jedem Suchschritt um 50% reduziert.

Wenn wir einen Array mit 1024 Elementen haben, besteht der erste Schritt in der Bestimmung der Mitte des Arrays und der Entscheidung, ob das Element bereits gefunden wurde bzw. in welcher Hälfte des Arrays man weitersuchen muss.

Der zweite Schritt arbeitet genau so wie der erste, nur die Anzahl der zu durchsuchenden Elemente hat sich auf 512 reduziert (streng genommen auf 511, weil ja nicht nur die eine Hälfte des Arrays wegfällt, sondern auch die Mitte des ursprünglichen Arrays).

Im dritten Schritt müssen nur noch 256 Elemente durchsucht werden, im vierten Schritt 128 und so weiter.

Die Zahl der Suchschritte entspricht also ungefähr dem Zweierlogarithmus der Anzahl der zu durchsuchenden Elemente. Für 1024 Elemente würde man also maximal 10 Suchschritte brauchen, für 10.000 Elemente maximal 14 Schritte.

Nähere Erklärung, falls nötig:

Spielen wir einmal mit dem Taschenrechner herum. Wie groß ist 210? Aha, genau 1024. Ein Array mit 1024 oder weniger Elementen sollte also nach maximal 10 Vergleichen erfolgreich durchsucht worden sein.

Berechnen wir nun 214. Das Ergebnis ist 16384. Für einen Array mit 10.000 Elementen sollte man also höchstens 14 Vergleiche benötigen, um eine Zahl zu finden bzw. um festzustellen, dass die Zahl nicht vorhanden ist. Auch ein Array mit 16.000 Elemente ist nach 14 Vergleichen durchsucht. Für einen Array mit 17.000 Elementen würde man dann höchstens 15 Vergleiche benötigen.

Aufgabe 12.2-1

Berechnen Sie die maximale Zahl der Vergleiche, die für eine Datei mit sämtlichen 83.000.000 Einwohnern der Bundesrepublik Deutschland notwendig wäre, um eine bestimmte Person zu finden.

Und um die Sache noch zu steigern: Wie sähe es bei einer Datei mit sämtlichen 7.550.000.000 Einwohnern der Erde aus (Stand Oktober 2022).

Lösungsvorschlag auf den Seiten für Lehrer(innen) / Nähere Infos dazu

Bei der linearen Suche hatten wir den Zeitaufwand O(N) = N charakterisiert. Bei der binären Suche ist der Zeitaufwand nur noch O(N) = log2 N, also erheblich geringer.

Nachteil der binären Suche

Auch die binäre Suche ist nicht die schnellste Suche, allerdings ist sie deutlich schneller als die lineare Suche.

Kommen wir noch einmal auf unser Bücher-Beispiel zurück. Wenn Sie nach dem russischen Science Fiction-Autor Isaac Asimov suchen, werden Sie im echten Leben mit Sicherheit nicht in der Mitte des Regals mit der Suche beginnen, sondern am Anfang des Regals, wo die Autoren stehen sollten, deren Nachname mit 'A' beginnt. Die binäre Suche kann also noch erheblich optimiert werden. Damit werden wir uns aber erst im übernächsten Kapitel beschäftigen, der Interpolationssuche und der Indexsuche.

Übungen zur binären Suche

Aufgabe 12.2-2

Eine Schülerin hat ein Flussdiagramm zur binären Suche gezeichnet:

Galdors Entwurf für die binäre Suche

Dieser Entwurf enthält leider noch einige Fehler. Suchen und korrigieren Sie die Fehler, indem Sie ein sauberes und fehlerfreies Flussdiagramm zeichnen, dass die binäre Suche darstellt.

Lösungshinweise...

Lösungsvorschlag auf den Seiten für Lehrer(innen) / Nähere Infos dazu

Übung 12.2-3

Erweitern Sie die Klasse Zahlenum eine Methode

public int suchzeitBinaer(int suchzahl)

welche den mit erzeugenSortiert erstellten Array nach der oben beschriebenen Methode des binären Suchens durchsucht und die Zahl der Vergleiche als Wert zurückliefert. Aber bitte nicht mogeln und einfach den Zweierlogarithmus berechnen; es soll die Zahl der tatsächlich benötigten Schritte ermittelt werden.

Lösungshinweise

Lösungsvorschlag auf den Seiten für Lehrer(innen) / Nähere Infos dazu

Übung 12.2-4

Erweitern Sie die Klasse Zahlenaus Übung 12.2-2 um eine Methode

public int suchzeitBinaerDurchschnitt()

welche die in Übung 12.2-3 implementierte Methode 20 mal aufruft. Bei jedem Aufruf wird zunächst eine Zufallszahl zwischen 1 und 1000 "gewürfelt" und dann an suchzeitBinaer übergeben.

Die Rückgabewerte werden addiert und am Ende durch 20 dividiert. Das Ergebnis dieser Division wird dann von der Methode suchzeitBinaerDurchschnitt zurückgegeben.

Lösungshinweise: Verfahren Sie ähnlich wie bei der Übung 12.1-5. Auch bei dieser Übung haben Sie zunächst eine Methode geschrieben, welche die Anzahl der Suchschritte ermittelt. Dann haben Sie diese Methode mit verschiedenen zufälligen Zahlen mehrmals ausführen lassen und anschließend die durchschnittliche Suchzeit berechnet.

Übung 12.2-5

Erweitern Sie die Klasse Zahlenaus Übung 12.2-3 so, dass die durchschnittliche Suchzeit für verschieden große Arrays automatisch ermittelt und ausgegeben wird. Eine mögliche Ausgabe könnte zum Beispiel so aussehen:

Durchschnittliche Suchzeit für 50 Zahlen = 5.75
Durchschnittliche Suchzeit für 100 Zahlen = 6.5
Durchschnittliche Suchzeit für 200 Zahlen = 7.5
Durchschnittliche Suchzeit für 400 Zahlen = 8.7
Durchschnittliche Suchzeit für 800 Zahlen = 9.5
Durchschnittliche Suchzeit für 1600 Zahlen = 10.6
Durchschnittliche Suchzeit für 3200 Zahlen = 11.65

Stellen Sie in Ihrem Heft die Abhängigkeit der durchschnittlichen Suchzeiten von der Größe des Arrays graphisch dar und bestimmen Sie, welches Zeitverhalten hier vorliegt (O-Notation, 3 Zusatzpunkte).

Lösungshinweise

Eine binäre Suche benötigt maximal lg2(N) Vergleiche, auch dann, wenn die Suche erfolglos ist.

Seitenanfang -
Weiter mit binären Suchbäumen...