具有动态项优先级的优先级队列

时间:2010-02-18 11:36:02

标签: algorithm heap priority-queue

我需要实现一个优先级队列,其中队列中项目的优先级可以更改,队列会自行调整,以便始终以正确的顺序删除项目。我有一些关于如何实现这一点的想法,但我确信这是一个非常常见的数据结构,所以我希望我可以使用比我更聪明的人作为基础的实现。

任何人都可以告诉我这种类型的优先级队列的名称,所以我知道要搜索什么,或者更好的是,指向我的实现?

5 个答案:

答案 0 :(得分:8)

此类优先级队列通常使用二进制堆数据结构实现,如其他人建议的那样,通常使用数组表示,但也可以使用二叉树。实际上,增加或减少堆中元素的优先级并不困难。如果您知道在从队列中弹出下一个元素之前更改了许多元素的优先级,则可以暂时关闭动态重新排序,在堆的末尾插入所有元素,然后重新排序整个堆(需要付出代价)在元素需要弹出之前的O(n))。关于堆的重要一点是,将数组放入堆顺序只需要O(n),而O(n log n)则需要对它进行排序。

我已经在具有动态优先级的大型项目中成功使用了这种方法。

以下是我对参数化priority queue implementation in the Curl programming language的实现。

答案 1 :(得分:5)

标准二进制堆支持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 :(得分:2)

我建议先尝试正面方法,更新优先级:

  • 从队列中删除项目
  • 使用新优先级重新插入

在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);
  }
}

答案 3 :(得分:0)

Google has a number of answers为您服务,包括one in Java的实施。

然而,这听起来像是一个家庭作业问题,所以如果是这样的话,我建议先尝试自己完成这些想法,然后如果你卡在某个地方需要指针,可能会引用其他人的实现。正确的方向。这样,您就不太可能对其他程序员使用的精确编码方法“偏向”,更有可能理解为什么每个代码都包含在内以及它是如何工作的。有时候,复制和粘贴相当于释义可能有点太诱人了。

答案 4 :(得分:0)

我正在寻找完全相同的东西!

以下是我的一些想法:

  1. 由于项目的优先级不断变化, 在检索项目之前对队列进行排序是没有意义的。
  2. 因此,我们应该忘记使用优先级队列。并且“部分”排序 检索物品时的容器。
  3. 并从以下STL排序算法中进行选择:    一个。划分    湾stable_partition    C。 nth_element    d。 partial_sort    即partial_sort_copy    F。分类    G。 stable_sort

    partition,stable_partition和nth_element是线性时间排序算法,应该是我们的第一选择。

    但似乎官方Java库中没有提供那些算法。因此,我建议您使用java.util.Collections.max / min来做你想要的。