算法导论——优先队列(大到小)

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");
		}
	}

}



转载于:https://my.oschina.net/u/1378920/blog/414521

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值