Ich muss den laufenden Median berechnen:
Eingabe: , , Vektor .
Ausgabe: Vektor , wobei der Median von .
(Kein Schummeln mit Näherungen; ich hätte gerne genaue Lösungen. Elemente sind große ganze Zahlen.)
Es gibt einen einfachen Algorithmus, der einen Suchbaum der Größe . Die Gesamtlaufzeit beträgt O ( n log k ) . (Hier bezieht sich ein "Suchbaum" auf eine effiziente Datenstruktur, die Einfügungen, Löschungen und mittlere Abfragen in logarithmischer Zeit unterstützt.)
Das kommt mir allerdings etwas blöd vor. Wir werden effektiv alle Ordnungsstatistiken in allen Fenstern der Größe lernen , nicht nur die Mediane. Darüber hinaus ist dies in der Praxis nicht allzu attraktiv, insbesondere wenn k groß ist (große Suchbäume sind in der Regel langsam, der Overhead beim Speicherverbrauch ist nicht trivial, die Cache-Effizienz ist oft schlecht usw.).
Können wir etwas wesentlich besser machen?
Gibt es Untergrenzen (z. B. ist der Trivialalgorithmus für das Vergleichsmodell asymptotisch optimal)?
Edit: David Eppstein gab eine schöne Untergrenze für das Vergleichsmodell! Ich frage mich, ob es trotzdem möglich ist, etwas Klügeres als den trivialen Algorithmus zu tun.
Könnten wir zum Beispiel etwas in diese Richtung tun: Teilen Sie den Eingabevektor in Teile der Größe ; sortiere jeden Teil (verfolge die ursprünglichen Positionen jedes Elements); und dann den stückweise sortierten Vektor verwenden, um die laufenden Mediane ohne zusätzliche Datenstrukturen effizient zu finden? Natürlich wäre dies immer noch O ( n log k ) , aber in der Praxis ist das Sortieren von Arrays in der Regel viel schneller als das Verwalten von Suchbäumen.
Bearbeiten 2: Saeed wollte einige Gründe sehen, warum das Sortieren meiner Meinung nach schneller ist als Suchbaumoperationen. Hier sind sehr schnelle Benchmarks für , n = 10 8 :
- ≈ 8s: Sortieren von Vektoren mit jeweils k Elementen
- ≈ 10s: Sortierung eines Vektors mit Elementen
- ≈ 80s: Einfügungen und Löschungen in einer Hash-Tabelle der Größe k
- ≈ 390s: Einfügungen und Löschungen in einem ausgeglichenen Suchbaum der Größe k
Die Hash-Tabelle dient nur zum Vergleich. Es ist in dieser Anwendung nicht direkt von Nutzen.
Zusammenfassend lässt sich sagen, dass sich die Sortierleistung im Vergleich zu ausgeglichenen Suchbaumoperationen um fast den Faktor 50 unterscheidet. Und es wird noch schlimmer, wenn wir erhöhen .
(Technische Details: Daten = zufällige 32-Bit-Ganzzahlen. Computer = ein typischer moderner Laptop. Der Testcode wurde in C ++ unter Verwendung der Standard-Bibliotheksroutinen (std :: sort) und Datenstrukturen (std :: multiset, std :: unsorted_multiset). Ich habe zwei verschiedene C ++ - Compiler (GCC und Clang) und zwei verschiedene Implementierungen der Standardbibliothek (libstdc ++ und libc ++) verwendet. Traditionell wurde std :: multiset als hochoptimierter Rot-Schwarz-Baum implementiert.)