【问题标题】:Priority queue with changing values of key具有更改键值的优先级队列
【发布时间】:2011-10-26 15:30:46
【问题描述】:

我必须模拟一个优先队列。队列中的键会定期更改。队列必须能够:添加元素和删除元素。最好的方法是什么(具有最好的复杂性)?最好的数据结构是什么?

【问题讨论】:

标签: java c++ algorithm data-structures


【解决方案1】:

我会推荐以下两种方法之一:

  1. (高级)使用 Java 的 PriorityQueue 实现所使用的堆数据结构。当元素的优先级发生变化时,您需要对堆执行“向上筛选”和“向下筛选”操作,以确保堆顶部仍然代表优先级队列中的最高元素。 Sift-up 和 sift-down 是构成heapsort 一部分的操作。
  2. (简单)使用无序列表作为优先队列。这意味着可以使用 O(1) 访问时间插入元素,并且调整元素的优先级不涉及对数据结构的任何操作。然而,代价是访问最高优先级的元素是 O(n)。

【讨论】:

  • 你的意思是找到更高的元素是 O(n),而不是 O(1)。另请注意,如果有 O(2^k) 总操作,则列表解决方案将具有价值,其中 k 是头部操作的数量。另请注意,建议 (1) 假设您拥有要修改的实际对象,而不仅仅是它的键,因为使用 java 的 PriorityQueue 从给定键中查找对象是 O(n)
  • 是的,这是一个公平的观点——我假设对象能够更新自己的优先级,或者应用程序已经引用了它;搜索它是低效的。
【解决方案2】:

如果您正在寻找一种数据结构,它可以支持任意键的不断变化,以及任意键的删除/添加[任意 == 不是此答案中的头部],那么常规堆将无法解决问题,因为它不能保证快速搜索任意元素,只能搜索到头部。

您可以使用完全有序的结构,例如 balanced BST,并在修改树时缓存最小值/最大值。 [最小值是最左边的元素,最大值是最右边的元素]。

这将允许您:
删除、修改、添加:O(logn)
findMin/findMax:O(1)

【讨论】:

  • 为什么不直接使用无序列表呢?这将允许您在 O(n) 中找到最小值/最大值,但插入将是 O(1)。
  • @Adamski:OP 想要一个优先级队列,所以我认为头部经常需要。请注意,仅当numOfAllOps = Omega(2^numHeadOps) 时,未排序的列表才会更好,我认为情况并非如此。
  • 如果更改是,那么我必须更改所有键。 BST 是否适用,何时必须通过一次“更改”操作更改所有键?
  • @user1014881:大多数 BST 实现不允许 change 操作,但您可以通过简单地删除并重新插入具有更改键的元素来创建一个,因为两个操作都是 O(logn),更改方法也将是O(logn)
  • 所以,我模拟了一个仓库。仓库中的每个项目都有优先级。物品进进出出。优先级最高的项目先出去。过程中可能需要“更改所有项目优先级”操作(填充和冲洗)。任何想法?塔克斯·彼得
【解决方案3】:

总是很难说什么是“最好的”数据结构。一般来说,二叉堆是一个非常好的优先级队列,尽管很难改变一个项目的优先级。我过去所做的是创建一个结合了字典和堆的数据结构。字典由项的标识符作为键,并跟踪每个项在堆中的位置。当在堆中添加、删除或移动项目时,它在字典中的位置会更新。事实证明这很便宜。

现在,当您想要更改项目的优先级或从优先级队列中删除任意项目时,您可以在字典 (O(1)) 中查找它以获取其在堆中的位置。从那里,移动或删除它是一个O(log n) 操作。

您还可以为优先级队列使用平衡二叉树。保持“最低节点”指针很容易,树上的操作是O(log n)。如果插入和删除相当分散,这应该表现得相当好。缺点是实现自平衡二叉树的代码有点复杂。

另一种可能性是使用skip list 作为您的优先队列。我的测试表明,跳过列表优先级队列优于基于二进制堆的优先级队列,但有一个很大的优势:查找项目是O(log n) 而不是O(n)。并且跳过列表并不比二叉堆更难实现。

我倾向于使用跳过列表,因为它比组合的堆/字典更容易管理,并且它的性能比平衡二叉树更好。

【讨论】:

    【解决方案4】:

    如果您只是将数字存储为键,则 ArrayList 类应该可以正常工作。

    queue = new ArrayList<int>;
    queue.add(27);
    

    【讨论】:

    • 但是。如果我要改变优先级,我必须通过“n”个元素。如果我要选择具有最高优先级的“m”个元素,我必须通过“m*n”。这不是最优的..
    猜你喜欢
    • 1970-01-01
    • 2012-02-24
    • 2012-04-21
    • 2023-04-02
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    相关资源
    最近更新 更多