Java中优先级队列的实现
Java中的优先级队列是通过PriorityQueue
类实现的,它是基于**优先级堆(通常是最小堆)**的数据结构。下面详细解析其实现机制:
核心实现原理
-
底层数据结构:
- 使用数组(
Object[] queue
)存储元素 - 逻辑上组织为二叉堆(默认是最小堆)
- 使用数组(
-
堆的性质维护:
- 父节点总是小于或等于子节点(最小堆)
- 插入和删除操作后通过"上浮"和"下沉"操作维护堆性质
关键操作实现
1. 插入元素(add/offer)
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length)
grow(i + 1); // 动态扩容
siftUp(i, e); // 上浮操作
size = i + 1;
return true;
}
上浮过程(siftUp):
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; // 找到最终位置
}
2. 删除元素(poll/remove)
public E poll() {
if (size == 0)
return null;
int s = --size;
modCount++;
E result = (E) queue[0];
E x = (E) queue[s];
queue[s] = null;
if (s != 0)
siftDown(0, x); // 下沉操作
return result;
}
下沉过程(siftDown):
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; // 找到最终位置
}
重要特性
-
动态扩容:
- 初始容量为11
- 扩容策略:小队列(<64)时双倍扩容,大队列时增长50%
-
排序方式:
- 默认自然顺序(最小堆)
- 可通过Comparator自定义优先级顺序
-
非线程安全:
- 线程安全版本使用
PriorityBlockingQueue
- 线程安全版本使用
-
时间复杂度:
- 插入/删除:O(log n)
- 查看队首:O(1)
使用示例
// 默认最小堆
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
minHeap.offer(5);
minHeap.offer(1);
minHeap.offer(3);
System.out.println(minHeap.poll()); // 输出1
// 自定义比较器实现最大堆
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);
maxHeap.offer(5);
maxHeap.offer(1);
maxHeap.offer(3);
System.out.println(maxHeap.poll()); // 输出5
Java的优先级队列实现高效且灵活,能够满足大多数需要优先级调度的应用场景。