【问题标题】:Priority Queue with overrided comparator具有覆盖比较器的优先级队列
【发布时间】:2020-11-10 17:45:34
【问题描述】:

我在 Java 中使用 PriorityQueue。

我有一个具有这种结构的对象:

public class CostObject {

  String value;
  double cost;

  public CostObject(String val, double cst) {
    value = val;
    cost = cst;
  }
}

优先级是从最便宜到最贵的成本:

PriorityQueue<CostObject> queue = new PriorityQueue<>(1, new Comparator<CostObject> () {

    @Override
    public int compare(CostObject co1, CostObject co2) {
            return (co1.cost > co2.cost) ? 1 : -1;
    }

});

我使用 add 将对象包含在队列中。

CostObject co = new CostObject("test", cost);
queue.add(co);

它适用于队列中的每个元素,但我添加的最后一个元素始终位于底部位置。

我做错了什么?

【问题讨论】:

  • 我建议也看看这个关于 PriorityQueue 的迭代器 stackoverflow.com/questions/5695017/… 的答案。如果您使用它来打印结果(或使用 PriorityQueue.toString),它们将不会按排序顺序。

标签: java priority-queue


【解决方案1】:

您的比较器永远不会返回 0。这至少违反了Comparator.compare 的一般合同中的一项规则,即:

sgn(compare(x, y)) == -sgn(compare(y, x))

如果xy 的成本相同,则compare(x, y)compare(y, x) 都将为-1。

你应该使用Double.compare,或者Comparator.comparingDouble来正确实现Comparator

new PriorityQueue<>(1, new Comparator<>() {
    public int compare(CostObject co1, CostObject co2) {
        return Double.compare(co1.cost, co2.cost);
    }
});

或者:

new PriorityQueue<>(1, Comparator.comparingDouble(CostObject::getCost));

正如 Slimu 在comments 中提到的,您可能会使用其iterator 将元素从队列中取出(例如使用for 循环)。这不能保证以正确的顺序为您提供元素,这可能就是“但我添加的最后一个元素始终位于底部位置”的原因。如果您希望元素按正确的顺序排列,您应该从队列中poll

【讨论】:

  • 我不明白为什么,但这不起作用,如果我检查队列,订单是推送的
  • @cucuru 如何“检查队列”?您是否有任何机会使用 for 循环?你应该从它那里poll
【解决方案2】:

优先级队列只会保证头部是最便宜的(或最小/最大,取决于比较器),但不保证整体顺序。 如果你 queue.poll() retrieveremove 头部,你会按顺序获取元素,因为每次轮询当前头部时,优先级队列都会确保新头是最便宜的元素

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-07
    相关资源
    最近更新 更多