package com.study.arithmetic;
/**
* 最大堆优先级队列.拥有4个功能:
* 1. 返回集合中具有最大关键字的元素
* 2. 返回并移除最大关键字的元素
* 3. 将某个元素的key值增加
* 4. 插入一个元素
* @author WeiY
*
*/
public class Maximum {
private int[] array;
private int heapSize;
public Maximum(int[] array) {
this.array = array;
heapSize = array.length;
buildMaxHeap(this.array);
}
public Maximum() {
array = new int[10];
heapSize = 0;
}
/**
* 返回集合中具有最大关键字的元素
* @return
*/
public int heapMaximum() {
return array[0];
}
/**
* 返回并移除最大关键字的元素
* @return
*/
public int heapExtractMax() {
if(heapSize < 1)
return -1;
int max = array[0];
heapSize--;
array[0] = array[heapSize];
maxHeapify(array, 0, heapSize);
return max;
}
/**
* 将某个元素的key值增加
* @param i
* @param key
*/
public void heapIncreaseKey(int i, int key) {
if(i > heapSize || i < 0 || key < array[i])
return;
array[i] = key;
while(i > 0 && array[parent(i)] < array[i]) {
swap(array, i, parent(i));
i = parent(i);
}
}
/**
* 插入一个元素
* @param key
*/
public void maxHeapInsert(int key) {
if(heapSize == array.length) {
int[] newArray = new int[array.length + 10];
System.arraycopy(array, 0, newArray, 0, array.length);
array = newArray;
}
array[heapSize] = Integer.MIN_VALUE;
heapIncreaseKey(heapSize, key);
heapSize++;
}
public int size() {
return heapSize;
}
/**
* 对数组做最大堆构建。
* 因为叶子节点没有子节点,我们只要对每个非叶子节点完成满足最大堆性质的调整(自底向上)。
* @param array
*/
private void buildMaxHeap(int[] array) {
int half = array.length / 2 - 1;
for(int i = half; i >= 0; i--)
maxHeapify(array, i, array.length);
}
/**
* 对每个非叶子最满足最大堆性质的调整。
* @param array
* @param i
* @param heapSize
*/
private void maxHeapify(int[] array, int i, int heapSize) {
int largest = i;
int l = left(i);
int r = right(i);
if(l < heapSize && array[l] > array[i])
largest = l;
if(r < heapSize && array[r] > array[largest])
largest = r;
if(largest != i) {
swap(array, largest, i);
maxHeapify(array, largest, heapSize);
}
}
private void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
private int left(int i) {
return 2 * i + 1;
}
private int right(int i) {
return 2 * (i + 1);
}
private int parent(int i) {
return (i-1) / 2;
}
public static void main(String[] args) {
// Maximum maximum = new Maximum(new int[]{4,1,3,2,16,9,10,14,8,7});
Maximum maximum = new Maximum();
maximum.maxHeapInsert(4);
maximum.maxHeapInsert(1);
maximum.maxHeapInsert(3);
maximum.maxHeapInsert(2);
maximum.maxHeapInsert(16);
int size = maximum.size();
for(int i = 0; i < size; i++)
System.out.println(maximum.heapExtractMax());
}
}