Zurück zu [[gf_informatik:suchen_und_sortieren#lineare_suche|Lineare Suche]] Weiter zu [[gf_informatik:suchen_und_sortieren:sortieren|Sortieren]]
Fast is better than slow. [[https://about.google/company-info/philosophy/?hl=en#:~:text=3.%20Fast%20is%20better%20than%20slow.|Google]]==== Binäre Suche ==== {{ :gf_informatik:binary_search.jpeg?nolink&400|}} === Aufgabe B1: Suchen in einem Wörterbuch / Lexikon === Zu zweit oder dritt: Eine Person wählt in einem Wörterbuch oder Lexikon heimlich einen Eintrag, der auf einer Seite rechts oben steht. Das Buch wird geschlossen und eine andere Person versucht mit möglichst wenigen Suchschritten (1x Blättern ist ein Schritt), den Begriff zu finden. Es ist dabei verboten, auf die Markierungen mit den Anfangsbuchstaben an der Seite des Buches zu schauen. Überlegt euch verschiedene Strategien, wie ihr vorgehen könnt. Welche Strategie benötigt die wenigsten Schritte? * Wie oft musst du blättern (bzw. die Seiten aufteilen), bis du das Wort gefunden hast? * Wie oft müsstest du durchschnittlich mit der linearen Suche blättern? * Wieviele Positionen (Finger zwischen den Seiten) musst du dir merken? === Algorithmus === Ist ein Datensatz nicht sortiert, macht eine lineare Suche Sinn. Ist dieser aber bereits sortiert, so gibt es viel effizientere Suchalgorithmen, wie die hier beschriebene **binäre Suche**: Wir teilen den Suchbereich ungefähr in der Mitte. Ist der Begriff zufälligerweise gleich dort, haben wir den Eintrag gefunden; ist der Begriff kleiner als das gefundene Element, suchen wir in der ersten Hälfte, sonst in der zweiten Hälfte weiter, bis genau ein einziges Element übrig bleibt. An dieser Stelle befindet sich der gesuchte Begriff, wenn er überhaupt vorhanden ist. Falls nicht, würde er an dieser Stelle eingefügt werden. {{:gf_informatik:binary_search.png?nolink&400|}} Bei der Suche im Wörterbuch suchen wir zu Beginn nur die richtige Seite - wir teilen den Suchbereich, indem wir die Mitte der verbleibenden Seiten wählen und den ersten Eintrag der Seite anschauen. Sind wir auf der richtigen Seite, wiederholen wir dasselbe mit den einzelnen Einträgen. #### Aufgabe B2: Binäre Suche berechnen 1. Eine Broschüre hat 7 Seiten und du möchtest mithilfe der binären Suche eine bestimmte Seite finden. Wie viele Seiten musst du maximal aufschlagen? Tipp: Zeichne auf einem Blatt vor dir 7 Striche, die die Seiten repräsentieren. 1. Wie sieht es mit einer Broschüre mit 15 oder 31 Seiten aus? Wie mit einem Buch mit 255 Seiten? 1. Erkennst du einen (mathematischen) Zusammenhang zwischen der Anzahl Seiten und der Anzahl Aufschlagen? 1. Stelle dir vor, es gäbe ein Telefonbuch für alle 8 Milliarden Menschen, wobei jede Person eine einzelne Seite hätte. Ist eine Seite 0.1mm dick, so wäre dieses Telefonbuch ca. 800km dick, was ungefähr der Distanz Romanshorn - London entspricht. Wie viele Seiten musst du maximal aufschlagen, um eine beliebige Person auf einer einzelnen Seite zu finden?
print(11 // 2)
>>> 5
++++
binary_search(l, v): Sie soll die Position von v in der Liste l zurückgeben. Wenn nichts gefunden wird, soll die Funktion None zurückgeben.
name den gesuchten Namen, also Lyanna.
index = binary_search(names, name) nach dem Index von name in der Liste names.
numbers die dazugehörige Telefonnummer.
Die Telefonnummer von ... ist ... aus.
name ändern musst, damit ein neuer, korrekter Satz ausgegeben wird.
binary_search().
linear_search(l, v) (am besten, du schreibst du sie selbst hin, anstatt sie zu kopieren).
stopwatch(algo, name). Sie hat zwei Argumente:
algo ist der Name der Suchfunktion (Suchalgorithmus), die verwendet werden soll (also binary_search oder linear_search, ohne die Klammern des Funktionsaufrufs).
name ist der Name, nach dem gesucht werden soll.
import time, siehe auch Aufgabe A5). Am Ende soll die Funktion einen Text in folgender Form ausgeben: "Die Telefonnummer von ... lautet .... Die Suche dauerte ... Sekunden."
Annina und Lyanna – jeweils mit der linearen und mit der binären Suche.
def binary_search2(li, el):
# dein Code hier!
my_list = ['A','A','C','E','E','E','E','E','G','G','G','G']
print(binary_search2(my_list,'A')) # Erwartete Ausgabe: [0, 1]
print(binary_search2(my_list,'B')) # Erwartete Ausgabe: None
print(binary_search2(my_list,'C')) # Erwartete Ausgabe: [2]
print(binary_search2(my_list,'D')) # Erwartete Ausgabe: None
print(binary_search2(my_list,'E')) # Erwartete Ausgabe: [3, 4, 5, 6, 7]
print(binary_search2(my_list,'F')) # Erwartete Ausgabe: None
print(binary_search2(my_list,'G')) # Erwartete Ausgabe: [8, 9, 10, 11]
print(binary_search2(my_list,'H')) # Erwartete Ausgabe: None
def binary_search2(li, el):
results = []
left = 0
right = len(li)-1
while left <= right:
mid = (left + right) // 2
if li[mid] == el:
while li[mid] == el:
mid -= 1
mid += 1
while mid < len(li) and li[mid] == el:
results.append(mid)
mid += 1
return results
elif li[mid] < el:
left = mid + 1
else:
right = mid -1
return None
++++
element == suche sind wir fertig.
suche < element, so ist das neue Suchintervall die linke Hälfte.
element < suche, das neue Suchintervall ist die rechte Hälfte.
Schreibe eine neue Funktion, binaere_suche_rekursiv(l, suche, links, rechts). Die Funktion codiert die obigen Schritte – statt einer while-Schleife soll die Funktion sich im Schritt 4 selber wieder aufrufen. Dieses Verfahren heisst Rekursion. Was sind die Startparameter für links und rechts?
Rekursion eignet sich für viele Probleme, die sich mit Divide & Conquer (Teile & Herrsche) lösen lassen: Probleme, die wir für den trivialen Fall mit einem Element lösen können, und die wir effizient von einem grösseren in ein kleineres Problem überführen können.