1. 普通队列和优先队列区别
- 普通队列:先入先出,后进后出;
- 优先队列:出队顺序和入队顺序无法;主要取决于“优先级”。
2. 二叉堆
- 二叉堆性质
- 底层是一棵二叉完全树(多余的数据,都要放在左子树这边,保证右子树为空。)
- 堆中某个节点的值,总是不大于其父节点的值,这样根节点就是值最大的节点;因此,也称为最大堆;最小堆则是:父节点的值总是小于子节点的值,因此,根节点是最小的值节点。
3. 最大堆源码
public class MaxHeap<T extends Comparable<T>> {
private ArrayList<T> data;
public MaxHeap() {
data = new ArrayList<>();
}
public MaxHeap(int capacity) {
data = new ArrayList<>(capacity);
}
public int getSize() {
return data.size();
}
public boolean isEmpty() {
return data.isEmpty();
}
public T findMax() {
if (getSize() == 0) {
throw new IllegalArgumentException("This array is empty!");
}
return data.get(0);
}
public T extractMax() {
T max = findMax();
swap(0, getSize() - 1);
data.remove(getSize() - 1);
siftDown(0);
return max;
}
private void siftDown(int k) {
while (leftChild(k) < getSize()) {
int leftChild = leftChild(k);
int rightChild = rightChild(k);
if (rightChild < getSize() && data.get(rightChild).compareTo(data.get(leftChild)) >= 0) {
leftChild = rightChild(k);
}
if (data.get(k).compareTo(data.get(leftChild)) >= 0) {
break;
}
swap(k, leftChild);
k = leftChild;
}
}
public void add(T data) {
this.data.add(data);
siftUp(this.data.size() - 1);
}
private void siftUp(int k) {
while (k > 0 && data.get(k).compareTo(data.get(parent(k))) > 0) {
swap(k, parent(k));
k = parent(k);
}
}
private void swap(int i, int j) {
if (i < 0 || j >= getSize() || j < 0 || i >= getSize()) {
throw new IllegalArgumentException("Index is illegal.");
}
T temp = data.get(i);
data.set(i, data.get(j));
data.set(j, temp);
}
private int parent(int index) {
if (index <= 0) {
throw new IllegalArgumentException(index + " haven't parent!");
}
return (index - 1) / 2;
}
private int leftChild(int index) {
return index * 2 + 1;
}
private int rightChild(int index) {
return index * 2 + 2;
}
}
4. 使用最大堆实现优先队列
public class PriorityQueue<T extends Comparable<T>> implements Queue<T> {
private MaxHeap<T> maxHeap;
public PriorityQueue() {
maxHeap = new MaxHeap<>();
}
@Override
public int getSize() {
return maxHeap.getSize();
}
@Override
public boolean isEmpty() {
return maxHeap.isEmpty();
}
@Override
public void enqueue(T element) {
maxHeap.add(element);
}
@Override
public T dequeue() {
return maxHeap.extractMax();
}
@Override
public T getFront() {
return maxHeap.findMax();
}
}