将值添加到优先级队列时,值的确切位置是什么?

时间:2017-09-26 12:08:22

标签: java sorting comparator priority-queue

考虑这个伪代码:

PriorityQueue <Integer> pq = new PriorityQueue(new Comparator()
{
    public int compare(Object o1, Object o2) 
    {
         Integer e1 = (Integer)o1;
         Integer e2 = (Integer)o2;
         if (e1 > e2) {return -1;}
         if (e2 > e1) {return 1;}
         return 0;
     }
});

pq.add(4);
pq.add(7);
pq.add(5);
pq.add(2);
pq.add(9);

现在我想知道,在运行时是否恰好在队列中运行compare()方法?我以为它会遵循这个顺序:

i)首先,数字4,7,5,2,9按顺序添加到队列中

ii)然后优先级队列使用compare方法对值进行排序

换句话说,首先将值插入队列中。然后他们排序。这个想法是否正确?或者在将值添加到队列中时对值进行排序?

2 个答案:

答案 0 :(得分:1)

PriorityQueues不是一种简单的排序数据结构,就像排序数组一样。 java中的PriorityQueue是使用优先级堆实现的。您应该了解堆的工作原理,但基本上在添加新元素时,会发生最大的log(n)比较。不必将所有元素相互比较。您可以在https://en.m.wikipedia.org/wiki/Priority_queue

了解有关优先级排队的详情

答案 1 :(得分:1)

PriorityQueue类为插入顺序(Comparator)定义了一个私有字段private final Comparator<? super E> comparator ...所以当你这样做时:

PriorityQueue<Integer> pq = new PriorityQueue<>(foo);

其中foo是比较器的一个实例,该对象将在内部为该实例初始化...

创建集合后,您开始向其添加元素,这就是魔术发生的地方。

只需查看PriorityQueue类,您将找到将被调用的方法siftUpUsingComparator,并使用您定义的比较器来验证插入顺序...

private void siftUpUsingComparator(int k, E x) {
    while (k > 0) {
        int parent = (k - 1) >>> 1;
        Object e = queue[parent];
        if (comparator.compare(x, (E) e) >= 0)
            break;
        queue[k] = e;
        k = parent;
    }
    queue[k] = x;
}

Offtopic:

你正在使用原始集合,这很糟糕,我觉得你的代码适应:

Comparator<Integer> foo = (o1, o2) -> {
    Integer e1 = o1;
    Integer e2 = o2;
    if (e1 > e2) {
        return -1;
    }
    if (e2 > e1) {
        return 1;
    }
    return 0;
};
PriorityQueue<Integer> pq = new PriorityQueue<>(foo);

pq.add(4);
pq.add(7);
pq.add(5);
pq.add(2);
pq.add(9);