robot-ya-builder 96458ea3c7 External build system generator release 65 9 months ago
..
ut bf0f13dd39 add ymake export to ydb 1 year ago
CMakeLists.darwin-arm64.txt ffff7a34e4 add darwin-arm64 CMakeLists 10 months ago
CMakeLists.darwin-x86_64.txt 33ed6077e6 Intermediate changes 1 year ago
CMakeLists.linux-aarch64.txt 9f448c9c67 Intermediate changes 1 year ago
CMakeLists.linux-x86_64.txt 33ed6077e6 Intermediate changes 1 year ago
CMakeLists.txt 96458ea3c7 External build system generator release 65 9 months ago
CMakeLists.windows-x86_64.txt 6324d075a5 Intermediate changes 1 year ago
README.md b56bb904dc intermediate changes 2 years ago
top_keeper.cpp fb1804b03a Restoring authorship annotation for <mbusel@yandex-team.ru>. Commit 2 of 2. 2 years ago
top_keeper.h 60d56d38e3 Restoring authorship annotation for <kcd@yandex-team.ru>. Commit 2 of 2. 2 years ago
ya.make bf0f13dd39 add ymake export to ydb 1 year ago

README.md

TopKeeper - структура данных для поддержания "top M from stream" Используется для выборки наибольших / наименьших элементов за один проход (полезно при фильтрации)

Пусть входной поток состоит из N элементов, из которых нужно отфильтровать M с наибольшим значением. Алгоритм (для случая top max M): 1) Выделим вектор размера 2 * M 2а) Если вектор заполнен меньше, чем наполовину - добавляем очередной элемент, обновляем минимум 2б) Иначе - сравниваем с текущим минимумом, в случае, если новый больше, добавляем его в вектор, минимум не обновляем, иначе - отбрасываем 3) Если заполнен - делаем Partition Sort с M-ым элементом в качестве сепаратора 4) Таким образом в левой половине все значения больше оных в правой, в позиции M стоит ровно M-ый элемент сортированной последовательности 5) Удаляем элементы из правой половины

Трудоёмкость: На M добавлений происходит 1 PartitionSort (усреднённая оценка трудоёмкости - О(M)) и удаление M элементов. Таким образом достигается О(1) операций в среднем на 1 добавление. Для алгоритма TLimitedHeap (library/cpp/containers/limited_heap) - эта оценка О(log (M))

Тесты: На случайных потоках данных количество сравнений у TopKeeper и LimitedHeap одинаково (происходит потому что минимум у первого обновляется раз в M добавлений, а у второго - при каждом добавлении). Худший случай LimitedHeap - сортированная последовательность (добавляем каждый элемент), на таком потоке для 2 000 000 000 int TopKeeper выигрывает во много раз.

Границы применимости: Применять стоит всегда вместо LimitedHeap (т.к. всегда не хуже, а в худшем случае - лучше) Ограничение - не поддерживает сценарий использования "чередующиеся добавления / извлечения элементов" (слишком часто будут происходить Partiotion Sortы) Для этого, когда добавление элементов закончено, должен вызываться метод Finalize(). Для упрощения использования добавлен автоматический Finalize() на GetNext() / Pop(). Тем не менее явный вызов Finalize() по-прежнему возможен - так можно контролировать момент выполнения трудоёмкой операции NthElement(). После того, как все элементы извлечены TopKeeper можно переиспользовать (для этого же служит метод Reset()). В ситуации когда нужны чередующиеся добавления / извлечения - используйте LimitedHeap

Примеры использования: library/cpp/containers/top_keeper/ut