Home > Informatik > Stufe Q1 > 12. Suchverfahren

12.5 Interpolationssuche

Überblick - Lineare Suche - Binäre Suche/Suchbäume - Sprungsuche - Indexsuche - Interpolationssuche

Grundidee

Wenn die Zahlen bzw. Elemente in dem Hauptarray einigermaßen gleichmäßig verteilt sind, benötigt man keinen Index-Array. Man kann versuchen, die Einstiegsposition für die Suche zu berechnen, zu interpolieren. Daher wird dieses Suchverfahren auch als Interpolationssuche bezeichnet.

asdf

50 sehr gleichmäßig verteilte Zahlen
Autor: Ulrich Helmich 2019, Lizenz: ---

Wir wollen hier nun nach vier dieser Zahlen suchen und wieder die durchschnittliche Suchzeit berechnen.

In dem Array befinden sich 50 Zahlen im Bereich zwischen 1 und 100. Wenn diese Zahlen einigermaßen gleichmäßig verteilt sind, kann man die Einstiegsposition für die Suche mit S/2 berechnen, wobei S die Suchzahl ist.

Wir wollen einmal die Zahl 50 suchen. Der Einstiegsindex ist dann 25. An der Position 25 finden wir die Zahl 52. Diese Zahl ist größer als die Suchzahl 50. Also suchen wir nach links weiter. Die erste Zahl, auf die wir stoßen, ist die 50, also die Suchzahl. Wir haben also 2 Vergleiche benötigt, um die 50 zu finden.

Die Zahl 61 ist wahrscheinlich ab Index 30 zu finden. Und dort ist sie auch, das heißt, wir haben nur 1 Vergleich benötigt, um die 61 zu finden.

Die Zahl 78 ist wahrscheinlich ab Index 39 zu finden. Dort steht die 79. Also suchen wir links weiter und finden sofort die 78. Auch hier haben wir nur 2 Vergleiche benötigt.

Auch die Zahl 94 finden wir nach 2 Vergleichen.

Die durchschnittliche Suchzeit für diese vier Zahlen liegt also unter 2,0. Eine solche Interpolationssuche ist also sehr effektiv, und man spart sich den Index-Array. Allerdings funktioniert die Interpolationssuche nur dann, wenn man die Einstiegsposition für die Suche auch tatsächlich einigermaßen zuverlässig berechnen kann. Dazu müssen die Elemente ziemlich gleichmäßig verteilt sein. Bei einer ungleichmäßigen Verteilung hilft dann aber immer noch die Indexsuche, die auf der vorherigen Seite erklärt wurde.

Umsetzung der Interpolationssuche

Stellen wir uns eine große sortierte Liste von Zahlen vor, beispielsweise 10.000 Zahlen mit Werten zwischen 1 und 100.000. Wir gehen davon aus, dass diese Zahlen annähernd gleichmäßig über den Wertebereich verteilt sind, aber dennoch einen gewissen Zufallscharakter besitzen.

import java.util.Random;

public class Zufallszahlen
{
    final int max = 10000;
    int[] liste;

    public Zufallszahlen()
    {
        liste = new int[max];
        create();
        show();
    }

    public void create()
    {
        Random wuerfel = new Random();

        liste[0] = wuerfel.nextInt(10) + 1;

        for (int i=1; i < max; i++)
            liste[i] = i*10 - 5 + wuerfel.nextInt(10);
    }

    public void show()
    {
        for (int i=0; i < max; i++)
        {
            System.out.print(liste[i] + "\t");

            if ((i+1)%10 == 0)
                System.out.println();
        }
    }
}

Mit diesem kleinen Java-Programm können wir eine solche Liste erzeugen. Die Zahlen sind annähernd gleichmäßig verteilt, besitzen aber einen zufälligen Anteil. Da sich die Werte aufeinanderfolgender Arrayelemente nicht überschneiden können, ist das Array stets aufsteigend sortiert. Hier ein Ausschnitt aus der Konsolenausgabe:

Ausschnitt aus der Konsolenausgabe mit aufsteigend sortierten Zufallszahlen

Ein Ausschnitt aus der Konsolenausgabe
Autor: Ulrich Helmich 2019, Lizenz: ---

Eine binäre Suche würde zunächst das mittlere Arrayelement untersuchen, das ungefähr den Wert 50.000 besitzt. Wir wollen aber die Zahl 3.000 suchen. Da die Zahlen annähernd gleichmäßig verteilt sind, können wir vermuten, dass sich die gesuchte Zahl ziemlich weit vorne im Array befindet.

Aber wo genau sollten wir mit der Suche beginnen? Hier kommt die Grundidee der Interpolationssuche ins Spiel: Wir schätzen die Position der Suchzahl anhand ihrer relativen Lage innerhalb des gesamten Wertebereichs.

Berechnung der Einstiegsposition

Bei der Interpolationssuche wird der vermutete Index der Suchzahl mit folgender Formel berechnet:

$\text{Position} = \frac{S - \text{array}[0]}{W} \cdot (L-1)$

Dabei bedeuten:

  • S = die Suchzahl
  • W = die Spannweite der Zahlen, also array[L-1] - array[0]
  • L = die Länge des Arrays
  • array[0] = der kleinste Wert im Array

Die Formel setzt voraus, dass das Array aufsteigend sortiert ist, die Suchzahl innerhalb des Wertebereichs liegt und die Spannweite größer als 0 ist. Je gleichmäßiger die Zahlen verteilt sind, desto genauer ist in der Regel die berechnete Position.

Erstes Suchbeispiel: Die Zahl 47

Betrachten wir dazu ein Array aus 50 sortierten int-Zahlen im Bereich von 2 bis 99:

Sortiertes Array mit 50 ganzen Zahlen zwischen 2 und 99

Die Spannweite W beträgt 99 - 2 = 97. Die Arraylänge L ist 50. Als Suchzahl wählen wir zunächst S = 47.

Mit der obigen Formel berechnen wir folgende Einstiegsposition:

$\text{Position} = \frac{47-2}{97} \cdot 49 = \frac{45}{97} \cdot 49 \approx 22{,}7$

Da ein Arrayindex ganzzahlig sein muss, schneiden wir den Nachkommateil des Ergebnisses ab. Wir beginnen daher bei Index 22. Dort steht die Zahl 46, die etwas kleiner als unsere Suchzahl ist.

Bei unserer etwas vereinfachten Variante der Interpolationssuche könnten wir nun sequentiell nach rechts weitersuchen. An Index 23 steht die Zahl 48, die bereits größer als unsere Suchzahl ist. Nach zwei Vergleichen mit Arrayelementen können wir die Suche also abbrechen: Die Zahl 47 kommt in diesem Array nicht vor.

Bei der eigentlichen Interpolationssuche würde man dagegen nach dem ersten erfolglosen Vergleich den Suchbereich verkleinern und innerhalb dieses Bereichs erneut eine Position berechnen. Auf diese Weise nähert man sich der gesuchten Zahl schrittweise an, ohne sämtliche dazwischenliegenden Elemente untersuchen zu müssen.

Zweites Suchbeispiel: Die Zahl 58

Versuchen wir es mit einer anderen Suchzahl. Diesmal suchen wir die Zahl 58, die tatsächlich im Array vorkommt.

$\text{Position} = \frac{58-2}{97} \cdot 49 = \frac{56}{97} \cdot 49 \approx 28{,}3$

Nach Abschneiden des Nachkommateils erhalten wir den Index 28. Dort steht tatsächlich die Zahl 58. Wir haben die Suchzahl also bereits beim ersten Vergleich gefunden!

Eine binäre Suche hätte dagegen fünf Suchschritte benötigt, um das Element an Index 28 zu finden. Sie hätte nacheinander die Indizes 24, 37, 30, 27 und schließlich 28 untersucht.

Fazit:

Unsere beiden Beispiele zeigen, wie leistungsfähig die Interpolationssuche bei annähernd gleichmäßig verteilten Zahlen sein kann. Während die binäre Suche den Suchbereich bei jedem Schritt ungefähr halbiert, versucht die Interpolationssuche, die Position der Suchzahl anhand ihres Wertes möglichst genau vorherzusagen.

Abitur Informatik NRW

Interessant ist hier die Diskrepanz zwischen den Abiturvorgaben und dem Kernlehrplan.

In den offiziellen Abiturvorgaben für das Informatik-Abitur findet sich gar nichts zum Thema "Suchverfahren". Bei dem Thema "Algorithmen" steht nur "Analyse, Entwurf und Implementierung von Algorithmen" und "Struktorgramme". Bei "Daten und ihre Strukturierung" finden sich "lineare Strukturen" wie "array bis zweidimensional", "Stapel", "Schlange" und "lineare Liste" sowie "nicht-lineare Strukturen" wie "Binärbaum" und "binärer Suchbaum".

In dem Kernlehrplan des Landes NRW dagegen steht auf Seite 22 unübersehbar: "Algorithmen zum Suchen und Sortieren". Hier die Unterpunkte:

Die Schülerinnen und Schüler

  • analysieren Such- und Sortieralgorithmen und wenden sie auf Beispiele an,
  • entwerfen einen weiteren Algorithmus zum Sortieren,
  • beurteilen die Effizienz von Algorithmen am Beispiel von Sortierverfahren hinsichtlich Zeitaufwand und Speicherplatzbedarf.

Der erste Unterpunkt bezieht sich direkt auf Suchverfahren, und zwar im Plural.

Also sollten Sie mindestens zwei verschiedene Suchverfahren kennen. Was bietet sich da besser an als die lineare bzw. sequentielle Suche und die binäre Suche. Wenn Sie dann noch die binäre Suche mit binären Suchbäumen in Verbindung setzen, haben Sie zumindest die mündliche Prüfung schon zu einem erheblichen Teil geschafft. Und wenn Sie dann auch noch auf den Unterschied zwischen Sprungsuche, Indexsuche und Interpolationssuche eingehen, wird Ihnen die Bewunderung von allen Mitgliedern der Prüfungskommission sicher sein.

Für Studierende in den ersten Semestern:

Zeitverhalten der Interpolationssuche KI-generiert

Dieser Abschnitt wurde nach meinen Vorgaben von ChatGPT erstellt und von mir dann etwas überarbeitet. Die überarbeitete Version habe ich dann von Mistral Vibe überprüfen lassen.

Die Interpolationssuche kann bei großen sortierten Arrays erheblich schneller sein als die binäre Suche. Voraussetzung ist allerdings, dass die Zahlenwerte annähernd gleichmäßig über den gesamten Wertebereich verteilt sind. Wie bei anderen Suchverfahren unterscheiden wir zwischen dem günstigsten Fall (Best Case), dem durchschnittlichen Fall (Average Case) und dem ungünstigsten Fall (Worst Case).

Best Case, Average Case und Worst Case

Best Case: Die durch Interpolation berechnete Position stimmt sofort mit der tatsächlichen Position der Suchzahl überein. Die Suche ist dann nach einem einzigen Vergleich erfolgreich. Die Zeitkomplexität beträgt O(1).

Average Case: Bei unabhängig und gleichmäßig verteilten Suchschlüsseln besitzt die klassische Interpolationssuche unter geeigneten Voraussetzungen eine durchschnittliche Zeitkomplexität von O(log log n). Die Zahl der notwendigen Suchschritte wächst also außerordentlich langsam mit der Arraylänge.

Worst Case: Bei sehr ungleichmäßig verteilten Zahlen können die berechneten Positionen weit von den tatsächlichen Positionen entfernt liegen. Im ungünstigsten Fall wird der Suchbereich bei jedem Schritt nur um ein einziges Element verkleinert. Die Zeitkomplexität beträgt dann O(n), die Zahl der Suchschritte wächst also linear mit der Arraylänge.

Vergleich mit der binären Suche

Die binäre Suche benötigt im ungünstigsten Fall O(log n) Suchschritte. Da bei jedem Schritt ungefähr die Hälfte des verbleibenden Suchbereichs ausgeschlossen wird, hängt ihre Laufzeit nicht von der Verteilung der Zahlenwerte ab.

Die Interpolationssuche ist bei gleichmäßig verteilten Suchschlüsseln im Durchschnitt dagegen mit O(log log n) noch günstiger. Wie groß der theoretische Unterschied ist, zeigen die folgenden Werte:

Arraylänge n log₂(n) log₂(log₂(n))
1.000 10,0 3,3
10.000 13,3 3,7
100.000 16,6 4,1
1.000.000 19,9 4,3

Die Tabelle zeigt, wie langsam die doppelt logarithmische Funktion wächst. Während sich der Logarithmus bei einer Vergrößerung des Arrays um den Faktor 1.000 ungefähr verdoppelt, nimmt der doppelte Logarithmus nur geringfügig zu.

Achtung: Die Tabellenwerte sind keine exakten Vergleichszahlen, sondern dienen lediglich dazu, das unterschiedliche Wachstum der beiden Funktionen zu veranschaulichen. Die O-Notation beschreibt das asymptotische Laufzeitverhalten und berücksichtigt weder konstante Faktoren noch den konkreten Rechenaufwand eines einzelnen Suchschrittes.

Warum ist die Interpolationssuche nicht immer schneller?

Die Berechnung einer neuen Position ist bei der Interpolationssuche aufwendiger als bei der binären Suche. Während die binäre Suche lediglich die Mitte des aktuellen Suchbereichs berechnen muss, benötigt die Interpolationssuche zusätzlich die Werte an den beiden Bereichsgrenzen und eine Division.

Bei kleineren Arrays kann dieser zusätzliche Rechenaufwand den Vorteil der geringeren Zahl von Suchschritten wieder aufheben. Außerdem kann eine ungünstige Verteilung der Zahlen dazu führen, dass die Interpolationssuche wesentlich mehr Schritte benötigt als die binäre Suche.

Die binäre Suche ist deshalb ein besonders robustes Suchverfahren: Sie garantiert auch bei sehr ungleichmäßig verteilten Zahlen eine logarithmische Laufzeit.

Kombination verschiedener Suchverfahren

Eine Möglichkeit zur Verbesserung besteht darin, verschiedene Suchstrategien miteinander zu kombinieren. Solche Verfahren bezeichnet man als Hybridverfahren.

Beispielsweise könnte man zunächst mit Hilfe der Interpolation eine günstige Einstiegsposition bestimmen. Anschließend wird der Suchbereich entsprechend dem Vergleichsergebnis verkleinert. Innerhalb dieses Bereichs kann man dann mit einer binären Suche fortfahren.

Eine andere Möglichkeit besteht darin, zunächst die klassische Interpolationssuche einzusetzen, aber nach einer bestimmten Anzahl erfolgloser Suchschritte zur binären Suche zu wechseln. Dadurch kann verhindert werden, dass eine ungünstige Verteilung der Zahlen zu einer sehr langen Suche führt.

Wird spätestens nach einer festen Anzahl von Interpolationsschritten auf die binäre Suche umgeschaltet, bleibt die Laufzeit auch im ungünstigsten Fall auf O(log n) begrenzt.

Interpolationssuche in der Praxis

Die Interpolationssuche eignet sich besonders für große sortierte Arrays mit annähernd gleichmäßig verteilten numerischen Suchschlüsseln. Voraussetzung ist außerdem, dass auf jedes Arrayelement direkt zugegriffen werden kann. Bei verketteten Listen wäre die Berechnung eines Index wenig hilfreich, weil man die entsprechende Position zunächst durchlaufen müsste.

Bei großen Datenbanken kommen für die Verwaltung von Suchindizes häufig spezielle Baumstrukturen zum Einsatz, insbesondere B-Bäume und B+-Bäume. Diese sind so organisiert, dass auch bei sehr großen Datenbeständen nur wenige Zugriffe auf Speicherblöcke notwendig sind.

Die Interpolationssuche ist daher vor allem ein interessantes Beispiel dafür, wie sich zusätzliche Informationen über die Verteilung von Daten ausnutzen lassen, um Suchverfahren zu beschleunigen. Sie zeigt zugleich, dass die theoretische Laufzeit eines Algorithmus nicht allein über seine praktische Leistungsfähigkeit entscheidet.

Seitenanfang -
Sie haben das Ende der Folge 12 erreicht.
Leistungskurs Informatik weiter mit Folge 13 (Quicksort)
Grundkurs Informatik weiter mit Folge 14 (Abstrakte Datentypen)