本篇文章為大家展示了怎么在Java中實現(xiàn)堆排序,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
在裕安等地區(qū),都構建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供成都網(wǎng)站建設、成都做網(wǎng)站 網(wǎng)站設計制作按需求定制網(wǎng)站,公司網(wǎng)站建設,企業(yè)網(wǎng)站建設,品牌網(wǎng)站制作,全網(wǎng)整合營銷推廣,成都外貿(mào)網(wǎng)站制作,裕安網(wǎng)站建設費用合理。堆排序是一種樹形選擇排序方法,它的特點是:在排序的過程中,將array[0,...,n-1]看成是一顆完全二叉樹的順序存儲結構,利用完全二叉樹中雙親節(jié)點和孩子結點之間的內(nèi)在關系,在當前無序區(qū)中選擇關鍵字大(最小)的元素。
1. 若array[0,...,n-1]表示一顆完全二叉樹的順序存儲模式,則雙親節(jié)點指針和孩子結點指針之間的內(nèi)在關系如下:
任意一節(jié)點指針 i:父節(jié)點:i==0 ? null : (i-1)/2
左孩子:2*i + 1
右孩子:2*i + 2
2. 堆的定義:n個關鍵字序列array[0,...,n-1],當且僅當滿足下列要求:(0 <= i <= (n-1)/2)
?、?array[i] <= array[2*i + 1] 且 array[i] <= array[2*i + 2]; 稱為小根堆;
?、?array[i] >= array[2*i + 1] 且 array[i] >= array[2*i + 2]; 稱為大根堆;
3. 建立大根堆:
n個節(jié)點的完全二叉樹array[0,...,n-1],最后一個節(jié)點n-1是第(n-1-1)/2個節(jié)點的孩子。對第(n-1-1)/2個節(jié)點為根的子樹調(diào)整,使該子樹稱為堆。
對于大根堆,調(diào)整方法為:若【根節(jié)點的關鍵字】小于【左右子女中關鍵字較大者】,則交換。
之后向前依次對各節(jié)點((n-2)/2 - 1)~ 0為根的子樹進行調(diào)整,看該節(jié)點值是否大于其左右子節(jié)點的值,若不是,將左右子節(jié)點中較大值與之交換,交換后可能會破壞下一級堆,于是繼續(xù)采用上述方法構建下一級的堆,直到以該節(jié)點為根的子樹構成堆為止。
反復利用上述調(diào)整堆的方法建堆,直到根節(jié)點。
4.堆排序:(大根堆)
①將存放在array[0,...,n-1]中的n個元素建成初始堆;
②將堆頂元素與堆底元素進行交換,則序列的大值即已放到正確的位置;
③但此時堆被破壞,將堆頂元素向下調(diào)整使其繼續(xù)保持大根堆的性質(zhì),再重復第②③步,直到堆中僅剩下一個元素為止。
堆排序算法的性能分析:
空間復雜度:o(1);
時間復雜度:建堆:o(n),每次調(diào)整o(log n),故最好、最壞、平均情況下:o(n*logn);
穩(wěn)定性:不穩(wěn)定
建立大根堆的方法:
//構建大根堆:將array看成完全二叉樹的順序存儲結構 private int[] buildMaxHeap(int[] array){ //從最后一個節(jié)點array.length-1的父節(jié)點(array.length-1-1)/2開始,直到根節(jié)點0,反復調(diào)整堆 for(int i=(array.length-2)/2;i>=0;i--){ adjustDownToUp(array, i,array.length); } return array; } //將元素array[k]自下往上逐步調(diào)整樹形結構 private void adjustDownToUp(int[] array,int k,int length){ int temp = array[k]; for(int i=2*k+1; i左孩子,則取右孩子節(jié)點的下標 } if(temp>=array[i]){ //根節(jié)點 >=左右子女中關鍵字較大者,調(diào)整結束 break; }else{ //根節(jié)點 <左右子女中關鍵字較大者 array[k] = array[i]; //將左右子結點中較大值array[i]調(diào)整到雙親節(jié)點上 k = i; //【關鍵】修改k值,以便繼續(xù)向下調(diào)整 } } array[k] = temp; //被調(diào)整的結點的值放人最終位置 }
堆排序:
//堆排序 public int[] heapSort(int[] array){ array = buildMaxHeap(array); //初始建堆,array[0]為第一趟值大的元素 for(int i=array.length-1;i>1;i--){ int temp = array[0]; //將堆頂元素和堆低元素交換,即得到當前大元素正確的排序位置 array[0] = array[i]; array[i] = temp; adjustDownToUp(array, 0,i); //整理,將剩余的元素整理成堆 } return array; }
刪除堆頂元素(即序列中的大值):先將堆的最后一個元素與堆頂元素交換,由于此時堆的性質(zhì)被破壞,需對此時的根節(jié)點進行向下調(diào)整操作。
//刪除堆頂元素操作 public int[] deleteMax(int[] array){ //將堆的最后一個元素與堆頂元素交換,堆底元素值設為-99999 array[0] = array[array.length-1]; array[array.length-1] = -99999; //對此時的根節(jié)點進行向下調(diào)整 adjustDownToUp(array, 0, array.length); return array; }
對堆的插入操作:先將新節(jié)點放在堆的末端,再對這個新節(jié)點執(zhí)行向上調(diào)整操作。
假設數(shù)組的最后一個元素array[array.length-1]為空,新插入的結點初始時放置在此處。
//插入操作:向大根堆array中插入數(shù)據(jù)data public int[] insertData(int[] array, int data){ array[array.length-1] = data; //將新節(jié)點放在堆的末端 int k = array.length-1; //需要調(diào)整的節(jié)點 int parent = (k-1)/2; //雙親節(jié)點 while(parent >=0 && data>array[parent]){ array[k] = array[parent]; //雙親節(jié)點下調(diào) k = parent; if(parent != 0){ parent = (parent-1)/2; //繼續(xù)向上比較 }else{ //根節(jié)點已調(diào)整完畢,跳出循環(huán) break; } } array[k] = data; //將插入的結點放到正確的位置 return array; }
測試:
public void toString(int[] array){ for(int i:array){ System.out.print(i+" "); } } public static void main(String args[]){ HeapSort hs = new HeapSort(); int[] array = {87,45,78,32,17,65,53,9,122}; System.out.print("構建大根堆:"); hs.toString(hs.buildMaxHeap(array)); System.out.print("\n"+"刪除堆頂元素:"); hs.toString(hs.deleteMax(array)); System.out.print("\n"+"插入元素63:"); hs.toString(hs.insertData(array, 63)); System.out.print("\n"+"大根堆排序:"); hs.toString(hs.heapSort(array)); }
上述內(nèi)容就是怎么在Java中實現(xiàn)堆排序,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注創(chuàng)新互聯(lián)網(wǎng)站建設公司行業(yè)資訊頻道。
另外有需要云服務器可以了解下創(chuàng)新互聯(lián)建站www.cdcxhl.com,海內(nèi)外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。