Java优先级队列未正确排序

时间:2013-06-04 19:27:49

标签: java sorting priority-queue comparable

我正在尝试实现类型BBNode的优先级队列,但它似乎没有像我期望的那样筛选新节点。而不是让最小的队列在队列的头部(它现在如何工作),我希望最大的存在,但我无法弄清楚如何使这项工作。这是我的BBNode课程。

public class BBNode implements Comparable<BBNode>{
    public int level; //level on the tree
    public int value; //value up to that node
    public int weight; //weight up to that node
    public double bound; //bound of that node

    //...constructors
    public int compareTo(BBNode node){
        if(this.bound > node.bound) return -1;
        if(this.bound < node.bound) return 1;
        return 0;
    }
}

这就是我使用PQ的地方。

PriorityQueue<BBNode> pq = new PriorityQueue<BBNode>();
//..other variables
while(pq.peek() != null){
  v = pq.poll();
  //System.out.println(v.weight + " " + v.value + " " + v.bound);
  if(v.bound >= bestVal && v.level < sortedItems.length-1){
     //left branch: take the next item
     u.level = v.level+1;
     u.weight = v.weight + sortedItems[u.level].weight;
     u.value = v.value + sortedItems[u.level].value;
     u.bound = bound(u);
     //System.out.println(u.bound);
     if(u.bound > bestVal){
        pq.add(u);
        System.out.println("adding " + u.bound);
        System.out.println("top of pq is " + pq.peek().bound);
     }
     if(u.weight <= maxWt && u.value > bestVal){
        bestVal = u.value;
        bestWt = u.weight;
        //System.out.println(bestVal + " " + bestWt);
        takeList[arrIdx++] = sortedItems[u.level].item+1;
     }
     //right branch: don't take the next item
     u.weight = v.weight;
     u.value = v.value;
     u.bound = bound(u);
     if(u.bound > bestVal){
        pq.add(u);
        System.out.println("adding " + u.bound);
        System.out.println("top of pq is " + pq.peek().bound);
     }
  }
}

抱歉,最后的格式很糟糕。最后一个括号对应于while循环。

我也尝试在比较方法中切换-1和1,我也尝试实现比较器,但结果相同。

感谢任何帮助:)

2 个答案:

答案 0 :(得分:3)

当您执行bound之类的操作时,您可能正在修改当前位于PriorityQueue的{​​{1}}个实例。第一次循环,你设置u.bound并将其放入,下次再次更改u.bound而不先将其从队列中拉出来。

如果您使用的是有组织的收藏集(u.bound = bound(u);HashSet/MapTreeSet/Map等),则会更改元素值,以便影响收藏的整理方式,你打破了该集合组织的假设,它们将以各种有趣的方式失败。我想这就是这里发生的事情。

有些问题可以在其他集合类型中讨论:

答案 1 :(得分:0)

另请注意,PriorityQueue(java 1.6)似乎是最好的努力 我在使用相同的比较器时使用PriorityQueue和ConcurrentSkipListSet进行单元测试时发现了这一点。
PriorityQueue尝试为新添加的项目找到正确的位置(它似乎走过节点但是在所有先前的项目较小之后一旦项目更大,反之亦然,队列停止查找并将项目放在最后一次检查的旁边)。
与阵列上的二进制搜索算法相比,它看起来好像搜索过程中的上限和下限是向右点靠近但是仍然存在间隙。 当我使用具有相同比较器的ConcurrentSkipListSet重复相同的测试时,该组实际上已正确排序!