Java 實現堆排序


 堆排序和合並排序一樣,是一種時間復雜度為O(nlgn)的算法,同時和插入排序一樣,是一種就地排序算法(不需要額外的存儲空間)。堆排序需要用到一種被稱為最大堆的數據結構,與java或者lisp的gc不一樣,這里的堆是一種數據結構,他可以被視為一種完全二叉樹,即樹里面除了最后一層其他層都是填滿的。也正是因為這樣,樹里面每個節點的子女和雙親節點的序號都可以根據當前節點的序號直接求出。

  Parent(i)=i/2

  Left(i)=2*i

Right(i)=2*i+1

 

 

如上圖所示,1位置的子女節點分別為2,3  2節點的子女節點為4,5 2的雙親節點為1 考察其他節點也很容易發現上述關系。最大堆是一種特殊的堆,其特點是每個雙親節點的值都比子女節點大。他的這一特點使得他可以實現nlgn的就地排序。現在我們先來看看怎么構建和保持一個最大堆。

最大堆的構建和保持

         我們現在有一個數組A,大小是n,假設其中元素按照完全二叉樹的方式排列。如何將其構造成一個最大堆?首先我們知道最大堆的每個子樹都符合最大堆的性質(根節點值大於所有子節點)。同時我們知道序號為(n/2+1)~n的元素都是葉子節點(因為其子女節點的序號都大於n,即說明沒有子女節點),因此我們構建最大堆的操作就在序號為1~n/2的元素內進行(其他元素已滿足最大堆性質)。我們定義如下操作maxify(i):將以i位置節點為根的子樹改造成最大堆。其操作內容如下:對於每個節點i,我們考察他與子女節點的大小,如果他比某個子女節點小,則將他與子女節點中最大的那個互換位置,然后在相應的子女節點位置重復操作,直到到達堆的葉子節點或者考察的位置比子女節點的值都要大為止。由此可知我們構造最大堆buildmaxheap的過程就是在每個內部節點上調用maxify過程,依次到樹的根部,此時其左右子樹都是最大堆,現在在根節點調用maxify即完成了最大堆的構造。

堆排序的操作

         有了最大堆的基礎結構后,我們就可以利用最大堆的性質進行排序HeapSort,我們從根節點開始操作,因為根節點是這個數組中最大的元素,因此我們將其於數組中最后一個元素對換(排序后,最大元素應該在最后)將heapsize減1,然后再在根節點出調用maxify過程將新的堆重新最大堆化。依次循環,我們每次都能將現有堆中最大的元素放到堆末尾。最后就完成了整個排序過程。操作情況見下圖(只列出了前4步)

        

package com.ys.sort;

import java.util.Arrays;
/*
 * 利用《大話數據結構》第9漲堆排序進行修改
 * 注意java中數組從0開始,節點s對應左右孩子是2s,2s+1;
 * 在java中節點s表示為a[s-1],左右孩子應為a[2s],a[2s-1]
*沒有用到遞歸 *
*/ public class HeapSort { public void heapSort(int[] array){ maxHeapAdjust(array); //構建成大頂錐 for(int i=array.length-1;i>0;i--){ swap(array,0,i); heapAdjust(array,1,i); //重新調整為大頂堆 } } public void maxHeapAdjust(int[] array){ for(int i=array.length/2;i>0;i--){//構建成大頂錐 heapAdjust(array,i,array.length); } } public void heapAdjust(int[] a,int s,int m){ int temp,i,largest; //largest中存關鍵字較大的記錄下標 temp = a[s-1]; //表示第s個節點 for(i=2*s;i<=m;i*=2){ if(i<m && a[i-1]<a[i]){ largest = i; ++i; }else largest = i-1; if(temp>=a[largest]) break; a[s-1] = a[largest]; s = largest+1; } a[s-1] = temp; } public void swap(int[] array,int from,int to){ int temp; temp = array[from]; array[from] = array[to]; array[to] = temp; } public static void main(String[] args) { HeapSort h = new HeapSort(); int[] a= {16, 14, 10, 8, 7, 9, 3, 2, 4, 1}; h.heapSort(a); String intArrayString = Arrays.toString(a); //將數組轉換為字符串打印輸出 System.out.print(intArrayString); } }

理論部分轉自http://www.cnblogs.com/developerY/p/3319618.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM