Всегда трудно сказать, что такое «лучшая» структура данных. В общем случае двоичная куча создает очередь с очень хорошим приоритетом, хотя изменить приоритет элемента сложно. В прошлом я занимался созданием структуры данных, которая объединяет словарь и кучу. Словарь определяется по идентификатору элемента и отслеживает местоположение каждого элемента в куче. Когда элемент добавляется, удаляется или перемещается в куче, его местоположение обновляется в словаре. Это оказывается недорого.
Теперь, когда вы хотите изменить приоритет элемента или удалить произвольный элемент из очереди приоритетов, вы можете найти его в словаре (O(1)
), чтобы получить его позицию в куче. Оттуда это O(log n)
операция по перемещению или удалению.
Вы также можете использовать сбалансированное двоичное дерево для своей очереди приоритетов. Достаточно просто сохранить указатель «самого низкого узла», и операции над деревом являются O(log n)
. Если вставки и удаления довольно хорошо рассеяны, это должно работать достаточно хорошо. Недостаток в том, что код для реализации самобалансирующегося двоичного дерева немного сложен.
Другой возможностью является использование списка пропуска для вашей приоритетной очереди. Мои тесты показывают, что очередь приоритетов с пропущенным списком выгодно отличается от очереди приоритетов на основе двоичной кучи, но имеет одно большое преимущество: поиск элемента O(log n)
вместо O(n)
. И список пропусков не намного сложнее реализовать, чем двоичная куча.
Я бы склонялся к использованию списка пропусков, потому что им легче управлять, чем комбинированной кучей / словарем, и он будет работать лучше, чем сбалансированное двоичное дерево.