1.2 Binäre Suche
Wenn wir im letzten Abschnitt eines gelernt haben, dann, dass lineare Suche schon bei kleineren Datenmengen zu viel Zeit benötigt. Falls Ihre Daten sortiert vorliegen, geht es schneller mit binärer Suche. Um das Prinzip der binären Suche zu verstehen, lade ich Sie dazu ein, ein kleines Spiel zu spielen.
Können Sie das gesuchte Wort mit höchstens sieben Klicks finden? Wahrscheinlich haben Sie rausgefunden, dass Sie als erstes irgendwo in der Mitte klicken sollten. Falls das dortige Wort "zu groß" ist, suchen Sie in der ersten Hälfte weiter; falls es zu klein ist, suchen Sie in der zweiten Hälfte weiter.
Versuchen wir nun, die Aufgabenstellung und das Prinzip der binären Suche
genauer zu verstehen. Wir haben ein sortiertes Array
Gegeben ein sortiertes Array
binarySearch(Array A, key x): l := -1, u := m while u - l > 1: m := (l+u)/2 if A[l] <= x then l = m else u = m return m
Die Funktion binarySearch(A,x)
gibt den größten Index
binarySearch
den Wert binarySearch
den Wert binarySearch
müsste laut unseren vorherigen Angaben also
sowohl binarySearch
im schlimmsten Falle durchläuft, in Abhängigkeit von
Behauptung.
Beweis.
Falls
Falls nun
Setzen wir
Wieviele Schritte braucht es, bis aus binarySearch
genau
binarySearch
auf einem
Array aus Der genaue Ausdruck
Also zum Beispiel
Vergleichen wir nun die binäre Suche mit der linearen. Falls das Array
Analog zu Set.java
habe ich OrderedSet.java
geschrieben.
Dies liest die (bereits sortierte) Datei english-words-58110.txt
ein
und beantwortet dann Anfragen. Vergleichen wir nun die Laufzeiten:
time java Set english-words-58110.txt < german-50000.txt > /dev/null
real 2m47.048s user 2m20.644s sys 0m1.403stime java SortedSet english-words-58110.txt < german-50000.txt > /dev/null
real 0m0.559s user 0m0.968s sys 0m0.120s
Durch binäre Suche haben wir die Laufzeit um einen Faktor von 300 reduziert!
Binäre Suche taucht auch oft auf, ohne dass explizit ein Array vorliegt.
Schreiben Sie in Java eine Funktion
public static int sqrt (int n)
, die die Funktion
Math.sqrt
oder
andere mathematische Bibliotheksfunktionen.
Ich habe Ihnen einen speziellen Algorithmus vorgestellt, der
das gegenwärtige Suchareal in jedem Schritt halbiert. Ist dies optimal?
Versuchen Sie zu beweisen, dass man im Schlimmsten Fall auch
-
Formulieren Sie in Gedanken die binäre Suche als Spiel . Bob kennt das Array
. In jedem Schritt fragt Alice einen index an und Bob antwortet mit . Alice will möglichst schnell den Wert finden, und Bob will dies verzögern. -
Tun Sie so, als wäre Bob ein adaptiver Gegner. Das heißt, er kann sich das
Array
Schritt für Schritt während des Spiels ausdenken. Er muss aber immer konsistent antworten, d.h. wenn Alice sowohl die Indizes angefragt hat, müssen Bobs Antworten die Bedingung erfüllen. -
Zeigen Sie, dass Sie den adaptiven Bob durch einen nicht-adaptiven Bob ersetzen können
(also durch
ein Array
, dass von vornherein feststeht), so dass Alice dennoch nicht schneller zum Ziel kommt (hier ist es wichtig, dass Alice deterministisch ist, also keinen Zufall verwenden darf).
Da binäre Suche ein ganz allgemeines Prinzip ist, ist es sinnvoll, es etwas abstrakter zu formulieren.
-
Wir haben ein sortiertes Array aus
ganzen Zahlen. Finde die erste nicht-negative Zahl. -
Wir haben ein Array aus
ganzen Zahlen, in welchem die negativen Zahlen links von allen positiven Zahlen stehen. Finde die erste positive Zahl. -
Wir haben ein Array
aus ganzen Zahlen, wobei und gelten. Finde einen Index mit .