60. Binary Search

Wir wollen nun eine tatsächlich nützliche Erweiterung schreiben. Dazu brauchen wir einige Präliminarien.

Ein häufig vorkommendes Problem ist die Suche in großen Datenmengen. Datenbanken (in Python kann man auf jeden Fall anydbm verwenden) sind ein Möglichkeit, es zu lösen, häufig ist es aber einfacher, die Daten in flat files zu halten, also einfachen Textdateien, in denen jede Zeile einem Eintrag entspricht. Um darin schnell Einträge zu finden, bietet sich binary search an.

Dabei müssen die Daten sortiert sein, und man geht vor wie beim Zahlenraten: Nimm den Eintrag in der Mitte, wenn der Suchschlüssel größer ist, mach in der oberen Hälfte weiter, sonst in der unteren, höre auf, wenn du den Eintrag gefunden hast oder sicher bist, dass du ihn nicht mehr findest. Das Python-Modul bisect implementiert das schon. Eine Funktion daraus:

def bisect_right(a, x, lo=0, hi=None):
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo+hi)//2
        if x < a[mid]: hi = mid
        else: lo = mid+1
    return lo

Wir wollen das für Textdateien haben, die z.B. so aussehen könnten:

a AP
AAA FW
Aarhus NP
Aaron NP
aback AVP
abacus NN
abalone NP
abandon VB

Dabei kommt als Komplikation gegenüber dem einfachen Fall oben hinzu, dass wir nicht wissen, wo die Datenfelder jeweils anfangen, denn die Textzeilen haben ja verschiedene Längen. Das Unix-Programm look kann damit aber umgehen. Wir möchten es jetzt in Python verwenden, und zwar ohne os.system oder Freunde.

Der Quelltext des BSD-Programms ist z.B. im Paket util-linux zu finden (vgl. Freshmeat) oder auch auf der Webseite zu dieser Vorlesung.

Übungen zu diesem Abschnitt

Ihr solltet euch wenigstens an den rötlich unterlegten Aufgaben versuchen

(1)

Wie viele Schritte braucht ein Binary Search im schlimmsten Fall, um ein gesuchtes Element aus einer Liste von N Elementen zu finden?


Markus Demleitner

Copyright Notice