什麼是優先隊列
快速得找到元素的最大或最小值。爲了實現這種數據結構
優先隊列便孕育而生。優先隊列或ADT是一種數據結構,支持插入和刪除最小值或最大值並返回最大值或最小值得操作。
優先隊列的應用
1.數據壓縮(赫夫曼編碼)
2.最短路徑
3.最小生成樹
4.選擇問題:查找第K個最小元素
優先隊列的實現
1.有序/無序數組實現
2.有序/無序鏈表實現
3.二叉樹實現
4.二叉堆實現
主要介紹二叉堆的實現
二叉堆是一棵具有特殊性質的二叉樹。
基本要求是所有節點必須大於或等於(小於或等於)其孩子節點
並且應該是一棵完全二叉樹
二叉堆的實現
/*
* 優先隊列是至少允許下列兩種操作的數據結構
* insert(插入) deleteMin(刪除最小)
* 優先隊列的工作是 找出 返回 刪除 優先隊列中的最小或最大元素
*
* 完全二叉堆實現優先隊列
* 利用完全二叉樹的緊湊性將完全二叉樹轉化爲數組形式
*/
public class BinaryHeap<T extends Comparable<? super T>> {
// 堆
private T[] heap;
// 當前大小
private int currentSize;
// 默認大小
private final static int DEFAULT_SIZE = 10;
public BinaryHeap() {
this(DEFAULT_SIZE);
}
// 打印二叉堆
public void printHeap() {
for (int i = 0; i < currentSize; i++)
System.out.print(this.heap[i] + ",");
}
@SuppressWarnings("unchecked")
public BinaryHeap(int size) {
heap = (T[]) new Comparable[size];
}
// 將一個數組轉化爲二叉堆
@SuppressWarnings("unchecked")
public BinaryHeap(T[] items) {
currentSize = items.length;
heap = (T[]) new Comparable[(currentSize + 2) * 11 / 10];
System.arraycopy(items, 0, heap, 0, items.length);
bulidHeap();
}
/*
* 對外開放的方法
*/
// 插入堆
public void insert(T t) {
// 數據臨界 擴一倍
if (currentSize == heap.length)
enlargeArray(heap.length * 2);
// 當前數量加一
currentSize++;
// 插入節點的序號
int i = currentSize - 1;
while (i > 0 && t.compareTo(heap[(i - 1) / 2]) > 0) {
// 插入數據大於其父節點的數據
heap[i] = heap[(i - 1) / 2];
// 下一個父節點
i = (i - 1) / 2;
}
heap[i] = t;
}
// 找到最大值
public T findMax() {
if (currentSize > 0)
return heap[0];
return null;
}
// 刪除最大值
public T deleteMax() {
T t = null;
if (currentSize > 0) {
t = heap[0];
// 將最後一個元素替代第一個
heap[0] = heap[currentSize - 1];
currentSize--;
percolateDown(0);
}
return t;
}
/*
* 私人方法
*/
// 下濾 (先找到孩子的最大值在與小於孩子的父節點互換)
private void percolateDown(int hole) {
// 判斷節點是否有孩子
int left = hole * 2 + 1;
T temp;
// 如果左孩子存在
if (left < currentSize) {
// 如果右孩子存在
if (left + 1 < currentSize) {
// 若右孩子大於左孩子互換
if (heap[left + 1].compareTo(heap[left]) > 0) {
temp = heap[left + 1];
heap[left + 1] = heap[left];
heap[left] = temp;
}
}
// 如果左節點大於父節點 互換
if (heap[left].compareTo(heap[hole]) > 0) {
temp = heap[hole];
heap[hole] = heap[left];
heap[left] = temp;
}
}
}
// 建立二叉堆
public void bulidHeap() {
// 調整所有節點 (currentSize表示當前堆中元素個數)
for (int i = (currentSize - 2) / 2; i >= 0; i--) {
percolateDown(i);
}
}
// 動態擴充數組變爲原來的兩倍
@SuppressWarnings("unchecked")
private void enlargeArray(int newSize) {
// 保存舊數據
T[] temp = heap;
// 擴一倍
heap = (T[]) new Comparable[2 * heap.length];
// 導入舊數據
System.arraycopy(temp, 0, heap, 0, temp.length);
}
}
至此,優先隊列的基礎介紹完畢。