java最小堆實現優先權佇列和求最大的n個數問題
阿新 • • 發佈:2019-01-22
堆在實現優先權佇列和求最大最小的n個數問題上,有著莫大的優勢!
對於最大堆和最小堆的定義此處不再贅述,課參考網上文章:http://blog.csdn.net/genios/article/details/8157031
本文主要是對最小堆進行實現和應用,僅供新手參考。
優先權佇列
優先權佇列是一種非常有用的資料結構,作業系統的程序排程就有優先權佇列的應用,如果用最小值表示最高的優先權,則使用最小堆,否則使用最大堆。
top-N值為問題:
對於求最大的n個數,可以用最小堆來實現,思路是:將n個數構建成一個最小堆,如果剩下的數有大於堆頂元素的值,則替換掉堆頂元素,再調整為最小堆,直到所有數字遍歷完。
貼上原始碼:
關鍵類:
package com.algorithms; /** * 最小堆,用陣列實現,解決top-N問題 * @author "zhshl" * @date 2014-10-22 * @param <T> */ public class Min_Heap { private int heap[]; private int maxSize; ////最多可容納數目 private int n;///元素數目 /** * @param num 堆的大小 */ public Min_Heap(int num){ n=0; maxSize=num; heap=new int[maxSize]; } /* *//** * 初始堆是一顆任意次序的完全二叉樹,從(n-2)/2處開始向下調整 * @param heap * @param n *//* public void createHeap(int[] heap2,int n){ heap=heap2; for(int i=(n-2)/2;i>=0;i--){ ///從(n-2)/2處開始向下調整 adjustDown(i,n-1); } }*/ /** * 元素入堆 * @param v */ public void append(int v){ if(isFull()){ System.out.println("heap is full ,can't append elements !"); return ; } ////元素插在末尾 heap[n]=v; n++; ///向上調整 adjustUp(n-1); } /** * 取出堆頂元素 * @return */ public int serve(){ if(isEmpty()){ System.out.println("heap is empty!"); return Integer.MIN_VALUE; } int temp=heap[0]; ////用最後一個元素取代第一個元素 heap[0]=heap[n-1]; n--; //向下調整 adjustDown(0, n-1); return temp; } /** * 求最大的n個數據 * @param data * @param n * @return null if n is bigger than the heap size, otherwise */ public int[] getTopN(int []data,int n){ heap=new int[n]; maxSize=n; this.n=0; ///構建初始堆 for(int i=0;i<n;i++){ append(data[i]); } for(int i=n;i<data.length;i++){ ////如果比堆頂元素大,則替換堆頂元素,並調整 if(data[i]>heap[0]){ heap[0]=data[i]; adjustDown(0, n-1); } } return heap; } /** * 對元素i進行向下調整,用於刪除元素時調整 * @param i * @param j */ private void adjustDown(int i, int j) { // TODO Auto-generated method stub int child=2*i+1; int temp=heap[i];///記錄待調整的節點的值 while(child<j){ ////在範圍內進行遍歷調整 if(heap[child]> heap[child+1]){ ///如果左孩子比右孩子大, 則指向較小的右孩子 child++; } if(heap[child]>temp){ ///如果較小的孩子都比自己大,則退出 break; } heap[(child-1)/2]=heap[child]; child=child*2+1; } ////迴圈結束,child指向最終位置的節點的左孩子 heap[(child-1)/2]=temp; } /** * 將i處的元素向上調整為堆,用於插入時候 * @param i */ private void adjustUp(int i){ int temp=heap[i]; while(i>0&&heap[(i-1)/2]> temp){ ///當父節點的值比temp大的時候,交換值 heap[i]=heap[(i-1)/2]; i=(i-1)/2; } heap[i]=temp; } /** * 堆是否滿了 * @return */ public boolean isFull(){ return n>=maxSize; } /** * 是否為空堆 * @return */ public boolean isEmpty(){ return 0==n; } }
測試類:
package com.algorithm.test; import com.algorithms.Min_Heap; /** * 最小堆測試類 * @author "zhshl" * @date 2014-10-22 * */ public class Min_Heap_Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Min_Heap heap=new Min_Heap(10); heap.append(2); heap.append(2); heap.append(13); heap.append(21); heap.append(2); heap.append(2); heap.append(53); heap.append(6); int temp; while(!heap.isEmpty()){ temp=heap.serve(); System.out.println(temp); } System.out.println("\n\n 求top-N問題:"); int data[]={4,51,52,12,123,52,7643,234,123,33,44,2}; data=heap.getTopN(data, 5); for(int i:data){ System.out.println(i); } } }