package org.loda.structure;
/**
*
* @ClassName: MaxQ
* @Description: 优先队列
*
* 顺序:大-->小
*
* 为了方便演示,目前只能存储int类型的整数,不过想要扩展也非常容易,加入比较器即可
*
* 为了纯粹的展现优先队列的操作,暂时不考虑添加元素超过数组长度导致数组扩容的情况,目前假设数组长度是足够的
*
* @author minjun
* @date 2015年5月13日 下午5:46:46
*
*/
public class MaxQ {
private int[] array;
private int heapSize;
public MaxQ() {
this(10);
}
public MaxQ(int size) {
array = new int[size];
}
/**
*
* @Title: offer
* @Description: 添加
* @param @param key 设定文件
* @return void 返回类型
* @throws
*/
public void offer(int key) {
// 将堆空间+1
heapSize++;
if(heapSize>array.length)
throw new RuntimeException("超过了队列长度");
// 为要添加的位置先占个坑
array[heapSize - 1] = Integer.MIN_VALUE;
//更新占位符所在的位置的值
insertKey(heapSize - 1, key);
}
private void insertKey(int i, int key) {
if(key<=array[i])
throw new RuntimeException("key必须要比i位置的值大");
array[i]=key;
//如果新添加进来的元素比父亲更大,那么互换位置
while(i>0&&array[i]>array[parent(i)]){
exchange(i, parent(i));
i=parent(i);
}
}
/**
*
* @Title: poll
* @Description: 取出
* @param @return 设定文件
* @return int 返回类型
* @throws
*/
public int poll() {
if (heapSize == 0)
throw new RuntimeException("没有元素了");
// 获取最大值,保存,并等待返回
int max = array[0];
// 将最后一个移动到开头,并重置最后一位的值
array[0] = array[heapSize - 1];
array[heapSize - 1] = 0;
// 将堆空间-1
heapSize--;
// 重新调整堆结构
maxHeapify(0);
return max;
}
/**
*
* @Title: size
* @Description: 返回堆空间大小
* @param @return 设定文件
* @return int 返回类型
* @throws
*/
public int size() {
return heapSize;
}
/**
*
* @Title: isEmpty
* @Description: 堆空间是否为空
* @param @return 设定文件
* @return boolean 返回类型
* @throws
*/
public boolean isEmpty(){
return size()==0;
}
private void maxHeapify(int i) {
// 获取堆中该元素的左孩子位置和右孩子位置
int l = left(i);
int r = right(i);
// 初始化最大元素的就是i位置的元素
int largest = i;
// 如果堆的左右孩子存在,并且有比他更大的,那么找出最大的那个
if (l <= heapSize - 1 && array[l] >= array[i]) {
largest = l;
}
if (r <= heapSize - 1 && array[r] >= array[largest]) {
largest = r;
}
if (largest != i) {
// 如果i不是最大值,那么将i和最大值换位
exchange(i, largest);
// 换位后,新的i索引处此时不见得可以满足堆性质,需要不断递归做验证
maxHeapify(largest);
}
}
/**
*由于数组索引是从0开始计算,那么左右元素的位置应该处于i*2+1和i*2+2的位置
*而父元素所在的位置应该是(i-1)/2
*/
private int right(int i) {
return i * 2 + 2;
}
private int left(int i) {
return i * 2 + 1;
}
public int parent(int i){
return (i-1)/2;
}
private void exchange(int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static void main(String[] args) {
MaxQ q=new MaxQ();
for(int i=0;i<10;i++){
q.offer(Math.round((float)Math.random()*100));
}
while(!q.isEmpty()){
System.out.print(q.poll()+"\t");
}
}
}