最大堆
MaxHeap.java
import java.util.Random; // 後面測試用
public class MaxHeap<E extends Comparable<E>> {
private Array<E> data;
public MaxHeap(int capacity){
data = new Array<>(capacity);
}
public MaxHeap(){
data = new Array<>();
}
/**
* 將數組轉化爲堆
* 一開始就把數組當成未規範的堆,
* 然後從第一個非葉子節點開始做sift down, 一直到根結點
* @param arr
*/
public MaxHeap(E[] arr){
data = new Array<>(arr);
for(int i=parent(arr.length-1); i>=0; i--){
siftDown(i);
}
}
public int size(){
return data.getSize();
}
public boolean isEmpty(){
return data.isEmpty();
}
/**
*
* @param index
* @return 父節點的索引
*/
private int parent(int index){
if(index == 0)
throw new IllegalArgumentException("No parent");
return (index-1)/2;
}
/**
*
* @param index
* @return 左孩子的索引
*/
private int leftChild(int index){
return index * 2 + 1;
}
/**
*
* @param index
* @return 右孩子的索引
*/
private int rightChild(int index){
return index * 2 + 2;
}
/**
* 添加元素e
* 思路: 把元素添加到最後一個, 然後向上浮動形成最大堆
* @param e
*/
public void add(E e){
data.addLast(e);
siftUp(data.getSize() - 1);
}
/**
* 向上浮動
* @param k
*/
private void siftUp(int k) {
// 一直循環, 如果k有父節點, 且比父節點大
while(k > 0 && data.get(parent(k)).compareTo(data.get(k)) < 0){
data.swap(k, parent(k));
k = parent(k);
}
}
/**
* 看最大的元素值
* @return
*/
public E findMax(){
if(data.getSize() == 0)
throw new IllegalArgumentException();
return data.get(0);
}
/**
* 取出堆中最大的元素
* 思路: 先保存最大元素, 然後用最後一個元素覆蓋掉最大的元素,
* 刪除最後一個元素, 然後向下浮動形成最大堆
* @return
*/
public E extractMax(){
E ret = findMax();
data.swap(0, data.getSize()-1);
data.removeLast();
siftDown(0);
return ret;
}
/**
* 向下浮動
* @param k
*/
private void siftDown(int k){
// 一直循環如果 k 有孩子
while(leftChild(k) < data.getSize()){
// 獲得最大的孩子的索引
int maxChildIndex = leftChild(k);
if(maxChildIndex+1 < data.getSize() &&
data.get(maxChildIndex).compareTo(data.get(maxChildIndex+1)) < 0){
maxChildIndex = rightChild(k);
}
// 如果根節點大於等於孩子
if(data.get(k).compareTo(data.get(maxChildIndex)) >= 0) {
break;
}
// 如果孩子比較大
data.swap(k, maxChildIndex);
k = maxChildIndex;
}
}
/**
* O(log n) 取出堆中最大的元素並替換成e
* @param e
* @return
*/
public E replace(E e){
E ret = findMax();
data.set(0, e);
siftDown(0);
return ret;
}
public static void main(String[] args) {
int n = 1000000;
MaxHeap<Integer> maxHeap = new MaxHeap<>();
Random random = new Random();
for(int i=0; i<n; i++){
maxHeap.add(random.nextInt(Integer.MAX_VALUE));
}
int[] arr = new int[n];
for(int i=0; i<n; i++){
arr[i] = maxHeap.extractMax();
}
for(int i=1; i<n; i++){
if(arr[i-1] < arr[i]){
throw new IllegalArgumentException();
}
}
System.out.println("Good!");
}
}
優先隊列
Queue.java
public interface Queue<E> {
int getSize();
boolean isEmpty();
void enqueue(E e);
E dequeue();
E getFront();
}
PriorityQueue.java
public class PriorityQueue<E extends Comparable<E>> implements Queue<E> {
private MaxHeap<E> maxHeap;
public PriorityQueue(){
maxHeap = new MaxHeap<>();
}
@Override
public int getSize() {
return maxHeap.size();
}
@Override
public boolean isEmpty() {
return maxHeap.isEmpty();
}
@Override
public void enqueue(E e) {
maxHeap.add(e);
}
@Override
public E dequeue() {
return maxHeap.extractMax();
}
@Override
public E getFront() {
return maxHeap.findMax();
}
}