По запросу, вот структура, которую я нашел после того, как сформулировал вопрос:
Основная идея состоит в том, чтобы использовать резьбовое дерево козла отпущения вместе с указателем на минимум (и, на всякий случай, максимум). Более простой альтернативой многопоточности является поддержание указателей предшественника и преемника в каждом узле (что эквивалентно, проще, но имеет больше накладных расходов). Я пришел, чтобы назвать это кучей козла отпущения , просто чтобы дать ей какое-то имя.
Именно эта базовая структура дает вам следующие операции:
- Поиск: по заданному ключу возвращает указатель на соответствующий узел за время.O(logn)
- Вставить: по заданному ключу вставляет ключ в структуру, возвращая указатель на этот узел за время.O(logn)
- Предшественник / преемник: при наличии указателя возвращает преемника или предшественника за время.O(1)
- Get-Min / Max: возвращает указатель на минимум или максимум.
При анализе деревьев козла отпущения, накладные расходы на удаление анализируются как , но на самом деле анализ дает накладные расходы на баланс (который игнорируется в статье поскольку они также подсчитывают время, необходимое для поиска узла, который должен быть удален). Итак, если у нас есть указатель на узел, мы можем удалить его за постоянное время (вы можете сделать это в многопоточном бинарном дереве поиска за время) и объединить с накладные расходы на балансировку, это дает время удаления:O ( 1 ) O ( log n ) O ( 1 ) O ( 1 ) O ( 1 )O(logn)O(1)O(logn)O(1)O(1)O(1)
- Удалить: при наличии указателя удаляет узел за время.O(1)
Сочетая это:
- Extract-Min / Max: удаляет минимальный / максимальный узел за время .O(1)
Вы можете сделать немного больше с указателями: например, нетрудно поддерживать указатель на медиану или некоторую другую статистику порядка, поэтому вы можете поддерживать постоянное количество таких указателей, если они вам нужны.
Некоторые другие вещи:
- Построение: учитывая ключей в отсортированном порядке, создайте кучу козла отпущения за время.nO(n)
- Баланс: сбалансируйте дерево так, чтобы оно сформировало идеально сбалансированное дерево двоичного поиска (сокращает накладные расходы на поиск) за время (вы можете сделать это постоянным фактором быстрее, чем, кстати, предложено в статье, используя указателей предшественника / преемника).O(n)
И, наконец, я почти уверен, что вы можете поддерживать эти операции, но мне нужно немного подумать об этом, прежде чем точно знать это:
- Insert-New-Min / Max: учитывая ключ, который меньше / больше любого ключа, уже существующего в структуре, вставляет ключ в структуру, возвращая указатель на этот узел за время.O(1)