Muszę obliczyć medianę biegu:
Dane wejściowe: , , wektor .
Wyjście: wektor , gdzie jest medianą .
(Brak oszustw z przybliżeniami; Chciałbym mieć dokładne rozwiązania. Elementy są dużymi liczbami całkowitymi.)
Istnieje prosty algorytm, który utrzymuje drzewo wyszukiwania o rozmiarze ; całkowity czas działania wynosi . („Drzewo wyszukiwania” odnosi się do wydajnej struktury danych, która obsługuje wstawianie, usuwanie i zapytania o medianę w czasie logarytmicznym).
Wydaje mi się to jednak trochę głupie. Skutecznie nauczymy się wszystkich statystyk zamówień we wszystkich oknach wielkości , nie tylko median. Co więcej, w praktyce nie jest to zbyt atrakcyjne, szczególnie jeśli jest duże (duże drzewa wyszukiwania są zwykle wolne, narzut w zużyciu pamięci nie jest trywialny, wydajność pamięci podręcznej jest często niska itp.).
Czy możemy zrobić coś znacznie lepszego?
Czy są jakieś dolne granice (np. Czy trywialny algorytm jest asymptotycznie optymalny dla modelu porównawczego)?
Edycja: David Eppstein podał dolną granicę dla modelu porównawczego! Zastanawiam się, czy można zrobić coś nieco sprytniejszego niż prosty algorytm?
Na przykład, czy moglibyśmy zrobić coś wzdłuż tych linii: podzielić wektor wejściowy na części wielkości ; posortuj każdą część (śledząc oryginalne pozycje każdego elementu); a następnie użyć wektora posortowanego w części, aby znaleźć działające mediany wydajnie bez żadnych struktur danych pomocniczych? Oczywiście nadal byłoby to , ale w praktyce sortowanie tablic jest zwykle znacznie szybsze niż utrzymywanie drzew wyszukiwania.
Edycja 2: Saeed chciał zobaczyć kilka powodów, dla których myślę, że sortowanie jest szybsze niż operacje drzewa wyszukiwania. Oto bardzo szybkie testy porównawcze, dla , :
- ≈ 8s: sortowanie wektorów z elementami każdy
- ≈ 10s: sortowanie wektora z elementami
- ≈ lata 80 .: wstawiania i usuwania w tablicy mieszającej o rozmiarze
- ≈ 390s: wstawiania i usuwania w zrównoważonym drzewie wyszukiwania o rozmiarze
Tabela skrótów jest tylko dla porównania; nie ma bezpośredniego zastosowania w tej aplikacji.
Podsumowując, mamy prawie 50-krotną różnicę w wydajności sortowania vs. zrównoważone operacje drzewa wyszukiwania. I wszystko pogorszy się, jeśli zwiększymy .
(Szczegóły techniczne: Dane = losowe 32-bitowe liczby całkowite. Komputer = typowy nowoczesny laptop. Kod testowy został napisany w C ++, przy użyciu standardowych procedur bibliotecznych (std :: sort) i struktur danych (std :: multiset, std :: unsorted_multiset). Użyłem dwóch różnych kompilatorów C ++ (GCC i Clang) oraz dwóch różnych implementacji biblioteki standardowej (libstdc ++ i libc ++). Tradycyjnie, std :: multiset został zaimplementowany jako wysoce zoptymalizowane drzewo czerwono-czarne.)