Приоритетная очередь с динамическими приоритетами элементов

Мне нужно реализовать очередь приоритетов, где приоритет элемента в очереди может измениться, и очередь настраивается так, чтобы элементы всегда удалялись в правильном порядке. У меня есть некоторые идеи о том, как я мог бы реализовать это, но я уверен, что это довольно распространенная структура данных, поэтому я надеюсь, что смогу использовать реализацию кем-то умнее меня в качестве базы.

может ли кто-нибудь сказать мне имя этого типа очереди приоритетов, чтобы я знал, что искать или, еще лучше, указать мне к реализации?

5 ответов


Я бы предложил сначала попробовать подход head-in, чтобы обновить приоритет:

  • удалить элемент из очереди
  • повторно вставьте его с новым приоритетом

В C++ это можно сделать с помощью std::multi_map, главное, что объект должен помнить, где он хранится в структуре, чтобы иметь возможность эффективно удалить самостоятельно. Для повторной вставки это сложно, так как вы не можете предположить, что знаете что-либо о приоритеты.

class Item;

typedef std::multi_map<int, Item*> priority_queue;

class Item
{
public:
  void add(priority_queue& queue);
  void remove();

  int getPriority() const;
  void setPriority(int priority);

  std::string& accessData();
  const std::string& getData() const;

private:
  int mPriority;
  std::string mData;

  priority_queue* mQueue;
  priority_queue::iterator mIterator;
};

void Item::add(priority_queue& queue)
{
  mQueue = &queue;
  mIterator = queue.insert(std::make_pair(mPriority,this));
}

void Item::remove()
{
  mQueue.erase(mIterator);
  mQueue = 0;
  mIterator = priority_queue::iterator();
}

void Item::setPriority(int priority)
{
  mPriority = priority;
  if (mQueue)
  {
    priority_queue& queue = *mQueue;
    this->remove();
    this->add(queue);
  }
}

очереди приоритетов, такие как это, обычно реализуются с использованием структуры данных двоичной кучи, как предложил кто-то другой, которая обычно представлена с помощью массива, но также может использовать двоичное дерево. На самом деле нетрудно увеличить или уменьшить приоритет элемента в куче. Если вы знаете, что изменяете приоритет многих элементов до того, как следующий элемент будет извлечен из очереди, вы можете временно отключить динамическое переупорядочение, вставьте все элементы в конце куча, а затем переупорядочить всю кучу(по стоимости O (n)) непосредственно перед тем, как элемент должен быть выскочил. Важно то, что в кучах стоит только O(n) поместить массив в порядок кучи, но o (n log n) отсортировать его.

Я успешно использовал этот подход в большом проекте с динамическими приоритетами.

вот моя реализация параметризованного реализация очереди приоритетов на языке программирования Curl.


стандартная двоичная куча поддерживает 5 операций (пример ниже предполагает максимальную кучу):

* find-max: return the maximum node of the heap
* delete-max: removing the root node of the heap
* increase-key: updating a key within the heap
* insert: adding a new key to the heap
* merge: joining two heaps to form a valid new heap containing all the elements of both.

Как вы можете видеть, в максимальной куче вы можете увеличить произвольный ключ. В куче min вы можете уменьшить произвольный ключ. Вы не можете изменить ключи в обе стороны, к сожалению, но это будет делать? Если вам нужно изменить ключи в обоих направлениях, вы можете подумать об использовании a мин-макс-кучи.


Google имеет ряд ответы для вас, включая реализацию один в Java.

тем не менее, это звучит как что-то, что было бы проблемой домашней работы, поэтому, если это так, я бы предложил сначала попытаться проработать идеи самостоятельно, а затем потенциально ссылаться на чужую реализацию, если вы застряли где-то и нуждаетесь в указателе в правильном направлении. Таким образом, вы с меньшей вероятностью будете "смещены" в сторону точного метода кодирования используется другим программистом и, скорее всего, поймет, почему каждый фрагмент кода включен и как он работает. Иногда может быть слишком заманчиво сделать перефразирующий эквивалент "копировать и вставлять".


Я ищу точно то же самое!

и вот некоторые из моих идей:

  1. поскольку приоритет элемента продолжает меняться, бессмысленно сортировать очередь перед извлечением элемента.
  2. Итак, мы должны забыть об использовании очереди приоритетов. И" частично " сортировать контейнер при получении товара.

и выберите один из следующих алгоритмов сортировки STL: раздел б. stable_partition С. nth_element д. partial_sort е. partial_sort_copy Ф. сортировать г. stable_sort

partition, stable_partition и nth_element-алгоритмы сортировки линейного времени, которые должны быть нашими 1-м выбором.

но, похоже, что в официальной библиотеке Java нет этих алгоритмов. В результате я предложу вам использовать java.утиль.Коллекции.макс / мин, чтобы сделать то, что вы хотите.