据我所知,min heap是该类使用的结构,因为它的效率。在我看来,当未分类的数据被提供给PQ时,它将它分类到堆中。
但是当根据compareTo方法向升序元素提供它时,它等待在PQ上执行第一个操作后将其排序到堆中。
你知道为什么吗?我不明白为什么它不会像无序数据那样自动排序。
我附上了一个我认为可以证明我的问题的程序。
输出:
未分类的数据:
[A,B,D,C,L,F,E,J]
A
[B,C,D,J,L,F,E]
[1,2,4,3,12,6,5,10]
1
[2,3,4,10,12,6,5]
排序数据:
[A,B,C,D,E,F,G,H]
A
[B,D,C,H,E,F,G]
[1,2,3,4,5,6,7,8]
1
[2,4,3,8,5,6,7]
import java.util.PriorityQueue;
public class Queue2
{
public static void main(String[] args)
{
PriorityQueue<String> pQueue = new PriorityQueue<String>();
pQueue.add("A");
pQueue.add("C");
pQueue.add("F");
pQueue.add("B");
pQueue.add("L");
pQueue.add("D");
pQueue.add("E");
pQueue.add("J");
System.out.println(pQueue);
System.out.println(pQueue.remove());
System.out.println(pQueue);
System.out.println();
PriorityQueue<Integer> pQueue2 = new PriorityQueue<Integer>();
pQueue2.add(1);
pQueue2.add(3);
pQueue2.add(6);
pQueue2.add(2);
pQueue2.add(12);
pQueue2.add(4);
pQueue2.add(5);
pQueue2.add(10);
System.out.println(pQueue2);
System.out.println(pQueue2.remove());
System.out.println(pQueue2);
System.out.println();
PriorityQueue<String> pQueue3 = new PriorityQueue<String>();
pQueue3.add("A");
pQueue3.add("B");
pQueue3.add("C");
pQueue3.add("D");
pQueue3.add("E");
pQueue3.add("F");
pQueue3.add("G");
pQueue3.add("H");
System.out.println(pQueue3);
System.out.println(pQueue3.remove());
System.out.println(pQueue3);
System.out.println();
PriorityQueue<Integer> pQueue4 = new PriorityQueue<Integer>();
pQueue4.add(1);
pQueue4.add(2);
pQueue4.add(3);
pQueue4.add(4);
pQueue4.add(5);
pQueue4.add(6);
pQueue4.add(7);
pQueue4.add(8);
System.out.println(pQueue4);
System.out.println(pQueue4.remove());
System.out.println(pQueue4);
}
}
答案 0 :(得分:2)
此队列的头部是指定排序的最小元素。如果多个元素绑定的值最小,则头部是其中一个元素 - 关系会被任意破坏。队列检索操作轮询,删除,查看和元素访问队列头部的元素。
并且
此类及其迭代器实现Collection和Iterator接口的所有可选方法。 方法iterator()中提供的迭代器不保证以任何特定顺序遍历优先级队列的元素。如果需要有序遍历,请考虑使用Arrays.sort(pq.toArray())。
这就是为什么当你打印队列(使用System.out)时,会使用内部迭代器,因此没有排序输出的保证......但如果多次使用poll()
,你肯定会看到返回的对象两种情况下的有序方式
答案 1 :(得分:0)
所以你知道队列中有一个(二进制)堆,对吗?堆应该遵循两个properties:
那么元素是如何插入的?只需做一个BFS,直到你找到一个空位(把元素放在那个位置),或者找到另一个比当前元素大的元素(用新元素替换那个元素并继续使用更大的元素)。
让我们通过两个例子来解决。我将逐级编写树,因此[A][BC][D---]
表示以A
为根,B
和C
子A
的树,和D
B
的孩子。
让我们看一下第一个例子:[A, C, F, B, L, D, E, J]
。这就是堆增长的方式:
[A]
[A][C-]
[A][CF]
[A][BF][C---]
[A][BF][CL--]
[A][BD][CLF-]
[A][BD][CLFE]
[A][BD][CLFE][J-------]
现在看看你的排序示例:[A, B, C, D, E, F, G, H]
。这就是堆增长的方式:
[A]
[A][B-]
[A][BC]
[A][BC][D---]
[A][BC][DE--]
[A][BC][DEF-]
[A][BC][DEFG]
[A][BC][DEFG][H-------]
实际上,底层数组按排序顺序包含所有元素。
那么,为什么在删除第一个元素时这个顺序会失真?为了满足两个堆属性,空白点重复填充该点的最小子节点。
让我们看一下删除A
后的最后一个例子(我用*
标记空白点):
[*][BC][DEFG][H-------]
[B][*C][DEFG][H-------]
[B][DC][*EFG][H-------]
[B][DC][HEFG]
这也与您提供的输出相对应。