Мені потрібно обчислити медіану бігу:
Вхід: , , вектор .
Вихід: вектор , де є медіаною .
(Немає обману з наближеннями; я хотів би мати точні рішення. Елементи - великі цілі числа.)
Існує тривіальний алгоритм, який підтримує дерево пошуку розміром ; загальний час роботи - . (Тут "дерево пошуку" відноситься до деякої ефективної структури даних, яка підтримує вставки, видалення та медіанні запити в логарифмічний час.)
Однак це здається мені трохи дурним. Ми ефективно вивчимо всю статистику замовлень у всіх вікнах розміром , а не тільки в медіанах. Більше того, це не надто привабливо на практиці, особливо якщо велике (великі дерева пошуку мають тенденцію бути повільними, надмірне споживання пам’яті нетривіальне, ефективність кеш-пам'яті часто погана тощо).
Чи можемо ми зробити щось істотно краще?
Чи є нижні межі (наприклад, чи є тривіальний алгоритм асимптотично оптимальним для моделі порівняння)?
Редагувати: Девід Еппштейн дав приємну нижню межу для моделі порівняння! Цікаво, чи все-таки можливо зробити щось трохи розумніше, ніж тривіальний алгоритм?
Наприклад, чи могли ми зробити щось за цими лініями: розділити вхідний вектор на частини розміром ; сортувати кожну частину (слідкуючи за вихідними положеннями кожного елемента); а потім використовувати кусково відсортований вектор, щоб ефективно знайти працюючі медіани без будь-яких допоміжних структур даних? Звичайно, це все-таки буде , але на практиці сортування масивів, як правило, відбувається набагато швидше, ніж підтримка дерев пошуку.
Редагування 2: Саїд хотів побачити деякі причини, чому я вважаю, що сортування відбувається швидше, ніж операції з пошуковим деревом. Ось дуже швидкі орієнтири, для , :
- ≈ 8s: сортування векторів з k елементами кожен
- ≈ 10s: сортування вектора з елементами
- ≈ 80-ті: вставок та видалень у хеш-таблиці розміром k
- ≈ 390s: вставок та вилучень у збалансованому дереві пошуку розміром k
Хеш-таблиця існує просто для порівняння; це не має прямого використання в цій програмі.
Підсумовуючи, ми маємо майже різницю в коефіцієнт 50 у ефективності сортування та збалансованих операцій із пошуковим деревом. І все стає набагато гірше, якщо ми збільшимо .
(Технічні деталі: Дані = випадкові 32-бітні цілі числа. Комп'ютер = типовий сучасний ноутбук. Тестовий код був написаний на C ++, використовуючи стандартні підпрограми бібліотеки (std :: сортування) та структури даних (std :: multiset, std :: unsorted_multiset) Я використав два різних компілятори C ++ (GCC та Clang) та дві різні реалізації стандартної бібліотеки (libstdc ++ та libc ++). Традиційно std :: multiset реалізований як високооптимізований червоно-чорний дерево.)