这个PriorityQueue有什么问题?

时间:2012-04-11 06:50:08

标签: java

fringe = new PriorityQueue<Node>(10,new Comparator<Node>(){
            @Override
            public int compare(Node node1,Node node2)
            {
                if (f(node1)>f(node2))
                    return 1;
                else
                    return -1;
            }
        });

我声明了一个PQ来存储一些节点,我想根据f值以非递减顺序存储节点。函数f(节点节点)是计算节点的f值。所以我覆盖了比较器,但是现在我发现一些f值较大的节点放在队列中f值较小的节点之前,我检查了一遍,但仍然找不到出错的地方,我想也许是PQ声明的问题。有人可以帮帮我吗?提前谢谢!

3 个答案:

答案 0 :(得分:6)

here。我引用:

The Iterator provided in method iterator() is not guaranteed to traverse the elements of the PriorityQueue in any particular order. If you need ordered traversal, consider using Arrays.sort(pq.toArray()).

所有保证的是顶部元素是根据比较器的最小元素。

答案 1 :(得分:1)

正如@izomorphius所述,PriorityQueue并不保证完整的排序,只是头部始终是最小的。

如果您想要完整订单 - 您可能想要选择以下其中一种可能性:

  1. 使用TreeSet - 但请注意,它不允许重复。另外,正如@JoonasPulakka所述,您可能还想覆盖equals()hashCode()
  2. 使用List - 填充[无序],然后使用Collections.sort(List,Comparator)根据比较器对其进行排序
  3. 使用数组[Node[]],填充[无序],然后使用Arrays.sort()根据比较器对其进行排序。
  4. 修改
    您的编辑比较器不强制执行完整排序,因此使用它的结果是不确定的: 允许abNode两个f(a) == f(b)

    compare(a,b) == compare(b,a) == -1
    

    但是javadocs州:

      

    实现者必须确保sgn(compare(x,y))== -sgn(比较(y,   x))所有x和y。

    因此,使用这个[编辑]比较器的结果是未定义的。

    <强> EDIT2:
    您的意见建议您正在寻找第二个标准 - “增加时间”。您可以向long timestamp对象添加其他字段Node,并且Comparator会根据此字段返回结果,当且仅当f(node1) == f(node2)时。这将保证一致性,并将实现所需的功能。

    注意:当您第一次向队列添加元素时[或者创建对象时,如果它是一个选项],此字段将被初始化一次[并且仅一次!]。

答案 2 :(得分:0)

您是否还覆盖了equals()?正如Comparator docs中指出的那样,

  

当使用能够强加与equals不一致的排序的比较器来排序有序集(或有序映射)时,应该小心。假设带有显式比较器c的有序集(或有序映射)与从集合S中绘制的元素(或键)一起使用。如果由S对S施加的排序与equals不一致,则排序集(或有序映射)将表现得“奇怪”。特别是有序集(或有序映射)将违反集合(或映射)的一般契约,它以等于的方式定义。

另请注意,当您覆盖equals()时,您还必须覆盖hashCode()Object docs中指出。

即使PriorityQueue不是(排序的)集合,如注释中所指出的,如果要切换数据结构,可以按特定顺序迭代(队列不能,排序集可以),然后最好完全按照建议实施compare()equals()hashCode()