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声明的问题。有人可以帮帮我吗?提前谢谢!
答案 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并不保证完整的排序,只是头部始终是最小的。
如果您想要完整订单 - 您可能想要选择以下其中一种可能性:
TreeSet
- 但请注意,它不允许重复。另外,正如@JoonasPulakka所述,您可能还想覆盖equals()
和hashCode()
。List
- 填充[无序],然后使用Collections.sort(List,Comparator)
根据比较器对其进行排序Node[]
],填充[无序],然后使用Arrays.sort()
根据比较器对其进行排序。 修改强>
您的编辑比较器不强制执行完整排序,因此使用它的结果是不确定的:
允许a
,b
为Node
两个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()
。