Очередь приоритетов с динамическими приоритетами элементов - PullRequest
16 голосов
/ 18 февраля 2010

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

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

Ответы [ 5 ]

8 голосов
/ 06 мая 2010

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

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

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

5 голосов
/ 18 февраля 2010

Стандартная двоичная куча поддерживает 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-max-heap .

2 голосов
/ 19 февраля 2010

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

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

В 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);
  }
}
0 голосов
/ 06 мая 2010

Я ищу одно и то же!

И вот моя идея:

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

И выбрать один из следующих алгоритмов сортировки STL: a.раздел б.стабильное разделение c.nth_element d.частичная_сортировка e.part_sort_copy f.сортировать г.stable_sort

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

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

0 голосов
/ 18 февраля 2010

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

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

...