PriorityQueue无法正常工作

时间:2016-09-06 18:22:14

标签: java priority-queue

我创建了一个插入对象的优先级队列,并将它们与成本参数进行比较,当两个成本相等时,它应该保持排队顺序,但我发现调试一次后它处于排队顺序而其他时间不是在顺序,但我没有得到我的代码有什么问题,我无法找到任何其他帖子帮助。

import java.util.*;
import java.lang.*;
import java.io.*;

class Node implements Comparable<Node>
{
    int x, y, dir;

    Node(int x, int y, int dir)
    {
        this.x = x;
        this.y = y;
        this.dir = dir;
    }

    public int compareTo(Node o)
    {
        if (Ideone.cost[o.x][o.y] == Ideone.cost[x][y]) {
            return 1;
        } else {
            int d = Ideone.cost[x][y] - Ideone.cost[o.x][o.y];
            if (d > 0) {
                return 1;
            } else {
                return -1;
            }
        }
    }
}

class Ideone
{
    public static int[][] cost;
    static PriorityQueue<Node> p;

    public static void main(String[] args)
        throws Exception
    {
        p = new PriorityQueue<Node>();

        cost = new int[13][11];

        for (int[] row : cost)
            Arrays.fill(row, -1);

        cost[0][8]  = 366564;
        cost[2][9]  = 368282;
        cost[1][3]  = 368282;
        cost[4][9]  = 368282;
        cost[0][9]  = 376564;
        cost[1][9]  = 372423;
        cost[5][9]  = 372423;
        cost[0][3]  = 436564;
        cost[7][0]  = 378282;
        cost[2][10] = 378282;
        cost[4][10] = 378282;
        cost[0][4]  = 382423;
        p.add(new Node(0, 8, 8));
        p.add(new Node(2, 9, 8));
        p.add(new Node(1, 3, 7));
        p.add(new Node(4, 9, 2));
        p.add(new Node(0, 9, 8));
        p.add(new Node(1, 9, 8));
        p.add(new Node(5, 9, 2));
        p.add(new Node(0, 3, 6));
        p.add(new Node(7, 0, 3));
        p.add(new Node(2, 10, 8));
        p.add(new Node(4, 10, 2));
        p.add(new Node(0, 4, 7));

        while (p.size() != 0) {
            Node n1 = p.poll();
            System.out.println(n1.x + " " + n1.y + " " + cost[n1.x][n1.y]);
        }
    }
}

输出

0 8 366564
1 3 368282
2 9 368282
4 9 368282
5 9 372423
1 9 372423
0 9 376564
4 10 378282
2 10 378282
7 0 378282
0 4 382423
0 3 436564

但我期待:

0 8 366564
2 9 368282
1 3 368282
4 9 368282
1 9 372423
5 9 372423
0 9 376564
7 0 378282
2 10 378282
4 10 378282
0 4 382423
0 3 436564

2 个答案:

答案 0 :(得分:0)

您需要 - 根据需要 - 遵循Peter Lawrey的建议,并将插入顺序存储在您插入优先级队列的每个节点中。在代码中解释起来更容易。您的节点类可能变为:

class Node implements Comparable<Node>
{
    int x, y, dir;
    /** the order in which the node was inserted into the priority queue (if it was) */
    int insertionOrder;

    Node(int x, int y, int dir, int insertionOrder)
    {
        this.x = x;
        this.y = y;
        this.dir = dir;
        this.insertionOrder = insertionOrder;
    }

    public int compareTo(Node o)
    {
        int d = Ideone.cost[x][y] - Ideone.cost[o.x][o.y];
        if (d == 0) {
            // keep insertion order
            return insertionOrder - o.insertionOrder;
        } else {
            return d;
        }
    }
}

你的主要方法:

public static void main(String[] args)
{
    p = new PriorityQueue<Node>();
    int numInserted = 0;

    cost = new int[13][11];

    for (int[] row : cost)
        Arrays.fill(row, -1);

    cost[0][8]  = 366564;
    cost[2][9]  = 368282;
    cost[1][3]  = 368282;
    cost[4][9]  = 368282;
    cost[0][9]  = 376564;
    cost[1][9]  = 372423;
    cost[5][9]  = 372423;
    cost[0][3]  = 436564;
    cost[7][0]  = 378282;
    cost[2][10] = 378282;
    cost[4][10] = 378282;
    cost[0][4]  = 382423;
    p.add(new Node(0, 8, 8, numInserted));
    numInserted++;
    p.add(new Node(2, 9, 8, numInserted));
    numInserted++;
    p.add(new Node(1, 3, 7, numInserted));
    numInserted++;
    p.add(new Node(4, 9, 2, numInserted));
    numInserted++;
    p.add(new Node(0, 9, 8, numInserted));
    numInserted++;
    p.add(new Node(1, 9, 8, numInserted));
    numInserted++;
    p.add(new Node(5, 9, 2, numInserted));
    numInserted++;
    p.add(new Node(0, 3, 6, numInserted));
    numInserted++;
    p.add(new Node(7, 0, 3, numInserted));
    numInserted++;
    p.add(new Node(2, 10, 8, numInserted));
    numInserted++;
    p.add(new Node(4, 10, 2, numInserted));
    numInserted++;
    p.add(new Node(0, 4, 7, numInserted));
    numInserted++;

    while (p.size() != 0) {
        Node n1 = p.poll();
        System.out.println(n1.x + " " + n1.y + " " + cost[n1.x][n1.y]);
    }
}

以上主要方法打印:

0 8 366564
2 9 368282
1 3 368282
4 9 368282
1 9 372423
5 9 372423
0 9 376564
7 0 378282
2 10 378282
4 10 378282
0 4 382423
0 3 436564

我相信这就是你的期望。

答案 1 :(得分:0)

PriorityQueue使用BinaryHeap来订购它的元素。这意味着不能保证在插入时将每个元素与其他元素进行比较(因此保留了相同元素的添加顺序)。为了保持相等元素的加法顺序,您需要在元素之间进行另一次比较。一种可能的方法是为每个节点使用时间戳

class Node implements Comparable<Node>
{
    int x, y, dir;
    Long timestamp = System.nanoTime();

    Node(int x, int y, int dir)
    {
        this.x = x;
        this.y = y;
        this.dir = dir;
    }

    public int compareTo(Node o){

        if (Ideone.cost[o.x][o.y] == Ideone.cost[x][y]) {
            return timestamp.compareTo(o.timestamp);
        }else {
            int d = Ideone.cost[x][y] - Ideone.cost[o.x][o.y];
            if (d > 0) {
                return 1;
            } else {
                return -1;
            }
        }
    }  
}

如果涉及多线程,则存在缺陷,在这种情况下,您需要存储添加顺序并使用该值进行比较

class Node implements Comparable<Node>
{
    int x, y, dir, pos;

    Node(int x, int y, int dir, int pos)
    {
        this.x = x;
        this.y = y;
        this.dir = dir;
        this.pos = pos;
    }

    public int compareTo(Node o){

        if (Ideone.cost[o.x][o.y] == Ideone.cost[x][y]) {
            Integer p1 = pos;
            return p1.compareTo(o.pos);
        }else {
            int d = Ideone.cost[x][y] - Ideone.cost[o.x][o.y];
            if (d > 0) {
                return 1;
            } else {
                return -1;
            }
        }
    }  
}

//then to add
p.add(new Node(0, 8, 8, p.size()));

当然,后一种方法有缺点,如果删除和添加项目是交错的(在这种情况下,你需要一个单独的变量来保持插入的增量)

int additionValue = 0;
p.add(new Node(0, 8, 8, additionValue++));