優先級隊列(堆實現)

(一)優先級隊列定義



(二)方法實現 

獲得最大元素方法


去掉最大元素方法



 修改優先級方法


添加節點


 

(三)實現

/**
 * 用堆實現一個優先級隊列
 * 主要是添加、修改、刪除節點
 * 節點具有唯一性
 * @author HHF
 * 2014年11月28日
 */
public class PriorityQueue {

	public static int HEAPSIZE;
	public static void main(String[] args) {
		int[] array = Common.random(0,100,10);
		HEAPSIZE = array.length;
		build(array);//建一個極大堆
		System.out.println("原始數據:");
		Common.print(array);
	
		//獲得最大值
		System.out.println("優先級最高的節點:"+maximum(array));
		
		//獲得並刪除最大值
		System.out.println("將要被刪除的優先級最高的節點:"+extractMax(array));
		System.out.println("刪除後的數據:");
		Common.print(array);
		
		//修改優先級
		increaseKey(array, 5, 100);
		System.out.println("修改後的數據:");
		Common.print(array);
		
		//添加節點
		insert(array, 101);
		System.out.println("插入後的數據:");
		Common.print(array);
		
		//刪除節點
		System.out.println("刪除的數據:"+delete(array, 1));
		System.out.println("刪除後的數據:");
		Common.print(array);
	}
	
	/**
	 * 返回優先隊列中優先級最高的節點
	 * @param array
	 * @return
	 */
	public static int maximum(int[] array){
		return array[0];
	}
	
	/**
	 * 去掉並返回優先級隊列中優先級最高的節點
	 * @param array
	 * @return
	 */
	public static int extractMax(int[] array){
		if(HEAPSIZE < 1){
			(new Exception("隊列內無元素    ")).printStackTrace();
			return 0;
		}
		//獲得最優節點
		int max = array[0];
		//刪除最優節點
		array[0] = array[--HEAPSIZE];
		//整理堆
		heapify(array, 0);
		//返回最優節點值
		return max;
	}
	
	/**
	 * 往優先隊列中插入節點
	 * 記得要去重
	 * @param array
	 * @param x
	 */
	public static void insert(int[] array, int x){
		array[HEAPSIZE++] = x-1;//加一個元素
		increaseKey(array, HEAPSIZE-1, x);
	}
	
	/**
	 * 將優先級爲x的節點優先級修改爲k
	 * @param array
	 * @param i被修改值下標
	 * @param k
	 */
	public static void increaseKey(int[] array, int i, int k){
		if(HEAPSIZE <= i){
			(new Exception("修改優先級節點下標有誤  ")).printStackTrace();
			return;
		}
		if(k <= array[i]){
			(new Exception("新節點的優先級被改低了  ")).printStackTrace();
			return;
		}
		//優先級被修改了
		array[i] = k;
		//整理隊列
		int parent = (i-1)/2; //父節點下標
		while(parent>-1 && array[parent]<array[i]){//到了必要交換子父節點的時候了
			Common.swap(array, parent, i);
			i = parent;
			parent = (i-1)/2;
		}
	}
	
	/**
	 * 將下標爲i的節點刪除 並返回其值
	 * @param array
	 * @param i
	 */
	public static int delete(int[] array, int i){
		if(HEAPSIZE <= i){
			(new Exception("刪除節點下標有誤  ")).printStackTrace();
			return 0;
		}
		//優先級被修改了
		int result = array[i];
		//整理隊列
		array[i] = -1;
		heapify(array, i);
		HEAPSIZE--;
		return result;
	}
	
	/**
	 * 將array變成一個極大堆
	 * @param array 堆
	 */
	public static void build(int[] array){
		int size = array.length;
		for(int i=size/2-1; i>=0; i--){
			heapify(array, i);
		}
	}
	
	/**
	 * 前提是i的左右孩子子樹均已經爲正常極大堆
	 * 將i調整爲正確位置
	 * @param array
	 * @param i 下標
	 */
	public static void heapify(int[] array, int i){
		int left = 2*i+1;//左孩子下標
		int right = left+1;//右孩子下標
		int large = 0;
		//選出left right 和  i 三個下標對應的最大值 記其下標爲large 
		if(left<HEAPSIZE  && array[left] > array[i]){
			large = left;
		}else{
			large = i;
		}
		if(right<HEAPSIZE && array[right] > array[large]){
			large = right;
		}
		//準備發生交換 和 遞推下一輪
		if(large != i){
			Common.swap(array, large, i);
			heapify(array, large);//此時的i所對應的值 已經 下移一層到了large
		}
	}
}

 (ps:附件內附上工具類Common.zip)

發佈了30 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章