【Java】PriorityQueue 的实现原理
2021-06-07 00:02
标签:使用 优先 数组 strong 理解 多个 初始 pat cep PriorityQueue 是基于优先级堆的无限优先级queue 。 优先级队列的元素根据它们的有序natural ordering ,或由一个 该队列的头部是相对于指定顺序的最小元素(即最小堆数据结构)。 如果多个元素被绑定到最小值,那么头就是这些元素之一 - 关系被任意破坏。 队列检索操作 优先级队列是无限制的,但是具有管理用于在队列上存储元素的数组的大小的内部容量 。 它始终至少与队列大小一样大。 当元素被添加到优先级队列中时,其容量会自动增长。 没有规定增长政策的细节。 注:不明白二叉堆-最小堆的可百度,即可理解原理 1、PriorityQueue 采用数组来存储数据的,数据结构是最小堆 2、PriorityQueue 扩容时 - 原容量小于 64,新容量为原容量的2倍+2 - 原容量不小于 64,新容量为原容量的1.5倍 3、放入元素,需要使用siftUp() 上浮方法,保证最小堆结构 4、取出元素,需要使用downtUp() 下浮方法,保证最小堆结构 5、PriorityQueue 非线程安全的,线程安全可以使用 PriorityBlockingQueue 【Java】PriorityQueue 的实现原理 标签:使用 优先 数组 strong 理解 多个 初始 pat cep 原文地址:https://www.cnblogs.com/h--d/p/14596772.html一、PriorityQueue介绍
Comparator
在队列构造的时候提供,这取决于所使用的构造方法。 优先队列不允许null
元素。 依靠自然排序的优先级队列也不允许插入不可比较的对象(这样做可能导致ClassCastException
)。poll
, remove
, peek
和element
访问在队列的头部的元件。二、属性
1 // 默认队列容量
2 private static final int DEFAULT_INITIAL_CAPACITY = 11;
3
4 // 数据数组
5 transient Object[] queue;
6
7 // 队列大小
8 private int size = 0;
9
10 // 比较器
11 private final Comparator super E> comparator;
12
13 // 修改次数
14 transient int modCount = 0;
三、方法
1、构造方法
1 // 创建默认优先级队列,队列默认容量为11,其中数据数组未创建
2 public PriorityQueue() {
3 this(DEFAULT_INITIAL_CAPACITY, null);
4 }
5
6 // 根据初始值容量创建优先级队列
7 public PriorityQueue(int initialCapacity) {
8 this(initialCapacity, null);
9 }
10
11 // 根据创建比较器,默认容量为11优先级队列
12 public PriorityQueue(Comparator super E> comparator) {
13 this(DEFAULT_INITIAL_CAPACITY, comparator);
14 }
15
16 // 根据初始值容量,比较器,创建队列
17 public PriorityQueue(int initialCapacity,
18 Comparator super E> comparator) {
19 // Note: This restriction of at least one is not actually needed,
20 // but continues for 1.5 compatibility
21 if (initialCapacity )
22 throw new IllegalArgumentException();
23 this.queue = new Object[initialCapacity];
24 this.comparator = comparator;
25 }
26
27 // 根据集合创建优先级队列
28 @SuppressWarnings("unchecked")
29 public PriorityQueue(Collection extends E> c) {
30 if (c instanceof SortedSet>) {
31 SortedSet extends E> ss = (SortedSet extends E>) c;
32 this.comparator = (Comparator super E>) ss.comparator();
33 initElementsFromCollection(ss);
34 }
35 else if (c instanceof PriorityQueue>) {
36 PriorityQueue extends E> pq = (PriorityQueue extends E>) c;
37 this.comparator = (Comparator super E>) pq.comparator();
38 initFromPriorityQueue(pq);
39 }
40 else {
41 this.comparator = null;
42 initFromCollection(c);
43 }
44 }
45
46 // 根据原优先级队列创建队列
47 @SuppressWarnings("unchecked")
48 public PriorityQueue(PriorityQueue extends E> c) {
49 this.comparator = (Comparator super E>) c.comparator();
50 initFromPriorityQueue(c);
51 }
52
53 // 根据SortSet集合创建优先级队列
54 @SuppressWarnings("unchecked")
55 public PriorityQueue(SortedSet extends E> c) {
56 this.comparator = (Comparator super E>) c.comparator();
57 initElementsFromCollection(c);
58 }
2、add() 和 offer() 方法
1 // 添加元素到队列中
2 public boolean add(E e) {
3 return offer(e);
4 }
5
6 // 放入元素到队列中
7 public boolean offer(E e) {
8 if (e == null)
9 throw new NullPointerException();
10 modCount++;
11 int i = size;
12 // 队列大小 大于等于 队列容量时
13 if (i >= queue.length)
14 // 对队列进行扩容
15 grow(i + 1);
16 size = i + 1;
17 if (i == 0)
18 // 队列中没有元素
19 queue[0] = e;
20 else)
21 // 使用的数组形式存储的“二叉堆”数据,上浮
22 // 二叉堆可自己百度
23 // 保持数据并上浮
24 siftUp(i, e);
25 return true;
26 }
3、grow() 方法
1 // 扩容
2 private void grow(int minCapacity) {
3 int oldCapacity = queue.length;
4 // Double size if small; else grow by 50%
5 // 1、原容量小于 64,新容量为原容量的2倍+2
6 // 2、原容量不小于 64,新容量为原容量的1.5倍
7 int newCapacity = oldCapacity + ((oldCapacity 8 (oldCapacity + 2) :
9 (oldCapacity >> 1));
10 // overflow-conscious code
11 if (newCapacity - MAX_ARRAY_SIZE > 0)
12 // 新容量大于数组最大长度时,新容量为:Integer.MAX_VALUE,否则为:MAX_ARRAY_SIZE
13 newCapacity = hugeCapacity(minCapacity);
14 // 复制数据到新数组
15 queue = Arrays.copyOf(queue, newCapacity);
16 }
4、siftUp() 方法
1 // 筛选 siftUp
2 private void siftUp(int k, E x) {
3 if (comparator != null)
4 siftUpUsingComparator(k, x);
5 else
6 siftUpComparable(k, x);
7 }
8
9 // 使用选择器上浮
10 @SuppressWarnings("unchecked")
11 private void siftUpComparable(int k, E x) {
12 Comparable super E> key = (Comparable super E>) x;
13 while (k > 0) {
14 int parent = (k - 1) >>> 1;
15 Object e = queue[parent];
16 if (key.compareTo((E) e) >= 0)
17 break;
18 queue[k] = e;
19 k = parent;
20 }
21 queue[k] = key;
22 }
23
24 // 使用选择器上浮
25 @SuppressWarnings("unchecked")
26 private void siftUpUsingComparator(int k, E x) {
27 while (k > 0) {
28 // 使用的
29 int parent = (k - 1) >>> 1;
30 Object e = queue[parent];
31 if (comparator.compare(x, (E) e) >= 0)
32 break;
33 queue[k] = e;
34 k = parent;
35 }
36 queue[k] = x;
37 }
5、poll() 方法
1 public E poll() {
2 if (size == 0)
3 return null;
4 int s = --size;
5 modCount++;
6 // 因为数据时最小堆,所以queue[0]最小
7 E result = (E) queue[0];
8 E x = (E) queue[s];
9 queue[s] = null;
10 if (s != 0)
11 // 二叉堆存储
12 // 下浮
13 siftDown(0, x);
14 return result;
15 }
6、siftDown() 方法
1 private void siftDown(int k, E x) {
2 if (comparator != null)
3 siftDownUsingComparator(k, x);
4 else
5 siftDownComparable(k, x);
6 }
7
8 @SuppressWarnings("unchecked")
9 private void siftDownComparable(int k, E x) {
10 Comparable super E> key = (Comparable super E>)x;
11 int half = size >>> 1; // loop while a non-leaf
12 while (k half) {
13 int child = (k // assume left child is least
14 Object c = queue[child];
15 int right = child + 1;
16 if (right 17 ((Comparable super E>) c).compareTo((E) queue[right]) > 0)
18 c = queue[child = right];
19 if (key.compareTo((E) c) )
20 break;
21 queue[k] = c;
22 k = child;
23 }
24 queue[k] = key;
25 }
26
27 @SuppressWarnings("unchecked")
28 private void siftDownUsingComparator(int k, E x) {
29 int half = size >>> 1;
30 while (k half) {
31 int child = (k ;
32 Object c = queue[child];
33 int right = child + 1;
34 if (right 35 comparator.compare((E) c, (E) queue[right]) > 0)
36 c = queue[child = right];
37 if (comparator.compare(x, (E) c) )
38 break;
39 queue[k] = c;
40 k = child;
41 }
42 queue[k] = x;
43 }
四、总结