PriorityQueue详解 PriorityQueue是优先级队列,底层使用数组存储,是基于二叉堆的一个无界队列,可以使用默认排序或者提供Comparator比较器使得队列中的元素有序,入栈出栈的时间复杂度是O(logn)
存储结构 堆树的定义
是一棵完全二叉树
某个节点的值总是不大于或不小于其孩子节点的值
每个节点的子树都是堆树
小顶堆 根节点的元素最小是小顶堆(小于左右子节点的值)
graph TD
0((0)) --- 1((1)) --- 3((3))
1((1)) --- 4((4))
0((0)) --- 2((2))
大顶堆 根节点的元素最大是大顶堆(大于左右子节点的值)
graph TD
0((4)) --- 1((3)) --- 3((1))
1((3)) --- 4((0))
0((4)) --- 2((2))
源码分析 是通过数组来存储的堆树,父子节点的下标关系为
leftNo = parentNo*2+1
rightNo = parentNo*2+2
parentNo = (nodeNo-1)/2
重要属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 private static final int DEFAULT_INITIAL_CAPACITY = 11 ;transient Object[] queue; private int size = 0 ;private final Comparator<? super E> comparator;transient int modCount = 0 ; private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8 ;
构造器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public PriorityQueue () { this (DEFAULT_INITIAL_CAPACITY, null ); } public PriorityQueue (int initialCapacity) { this (initialCapacity, null ); } public PriorityQueue (Comparator<? super E> comparator) { this (DEFAULT_INITIAL_CAPACITY, comparator); } public PriorityQueue (int initialCapacity, Comparator<? super E> comparator) { if (initialCapacity < 1 ) throw new IllegalArgumentException(); this .queue = new Object[initialCapacity]; this .comparator = comparator; } @SuppressWarnings("unchecked") public PriorityQueue (Collection<? extends E> c) { if (c instanceof SortedSet<?>) { SortedSet<? extends E> ss = (SortedSet<? extends E>) c; this .comparator = (Comparator<? super E>) ss.comparator(); initElementsFromCollection(ss); } else if (c instanceof PriorityQueue<?>) { PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c; this .comparator = (Comparator<? super E>) pq.comparator(); initFromPriorityQueue(pq); } else { this .comparator = null ; initFromCollection(c); } } @SuppressWarnings("unchecked") public PriorityQueue (PriorityQueue<? extends E> c) { this .comparator = (Comparator<? super E>) c.comparator(); initFromPriorityQueue(c); } @SuppressWarnings("unchecked") public PriorityQueue (SortedSet<? extends E> c) { this .comparator = (Comparator<? super E>) c.comparator(); initElementsFromCollection(c); }
常用方法 获取顶端元素 1 2 3 4 public E peek () { return (size == 0 ) ? null : (E) queue[0 ]; }
插入 以使用默认比较器为例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 public boolean add (E e) { return offer(e); } public boolean offer (E e) { if (e == null ) throw new NullPointerException(); modCount++; int i = size; if (i >= queue.length) grow(i + 1 ); size = i + 1 ; if (i == 0 ) queue[0 ] = e; else siftUp(i, e); return true ; } private void grow (int minCapacity) { int oldCapacity = queue.length; int newCapacity = oldCapacity + ((oldCapacity < 64 ) ? (oldCapacity + 2 ) : (oldCapacity >> 1 )); if (newCapacity - MAX_ARRAY_SIZE > 0 ) newCapacity = hugeCapacity(minCapacity); queue = Arrays.copyOf(queue, newCapacity); } private void siftUp (int k, E x) { if (comparator != null ) siftUpUsingComparator(k, x); else siftUpComparable(k, x); } private void siftUpComparable (int k, E x) { Comparable<? super E> key = (Comparable<? super E>) x; while (k > 0 ) { int parent = (k - 1 ) >>> 1 ; Object e = queue[parent]; if (key.compareTo((E) e) >= 0 ) break ; queue[k] = e; k = parent; } queue[k] = key; }
添加元素位于末尾,同时队列长度加1,然后这个元素与它的父节点进行比较,如果比父节点小就与父节点进行交换,重复此过程,直到元素大于父节点结束该过程
删除 还是以默认的比较器为例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 public boolean remove (Object o) { int i = indexOf(o); if (i == -1 ) return false ; else { removeAt(i); return true ; } } private int indexOf (Object o) { if (o != null ) { for (int i = 0 ; i < size; i++) if (o.equals(queue[i])) return i; } return -1 ; } private E removeAt (int i) { modCount++; int s = --size; if (s == i) queue[i] = null ; else { E moved = (E) queue[s]; queue[s] = null ; siftDown(i, moved); if (queue[i] == moved) { siftUp(i, moved); if (queue[i] != moved) return moved; } } return null ; } private void siftDown (int k, E x) { if (comparator != null ) siftDownUsingComparator(k, x); else siftDownComparable(k, x); } private void siftDownComparable (int k, E x) { Comparable<? super E> key = (Comparable<? super E>)x; int half = size >>> 1 ; while (k < half) { int child = (k << 1 ) + 1 ; Object c = queue[child]; int right = child + 1 ; if (right < size && ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0 ) c = queue[child = right]; if (key.compareTo((E) c) <= 0 ) break ; queue[k] = c; k = child; } queue[k] = key; } private void siftUp (int k, E x) { if (comparator != null ) siftUpUsingComparator(k, x); else siftUpComparable(k, x); } private void siftUpComparable (int k, E x) { Comparable<? super E> key = (Comparable<? super E>) x; while (k > 0 ) { int parent = (k - 1 ) >>> 1 ; Object e = queue[parent]; if (key.compareTo((E) e) >= 0 ) break ; queue[k] = e; k = parent; } queue[k] = key; }