選擇排序是常用內部排序的一種,常見的實現演算法有直接選擇排序演算法和堆排序演算法,選擇排序的基本思想是每次從待排資料中選擇第n小的資料放到排序列表的第n個位置,假如共有N個資料待排,那麼經過N-1次排序後,待排資料就已經按照從小到大的順序排列了。
直接選擇排序演算法的思想比較簡單:(假設資料放在一個數組a中,且數組的長度是N)
1:從a[0]-a[N-1]中選出最小的資料,然後與a[0]交換位置
2:從a[1]-a[N-1]中選出最小的資料,然後與a[1]交換位置(第1步結束後a[0]就是N個數的最小值)
3:從a[2]-a[N-1]中選出最小的資料,然後與a[2]交換位置(第2步結束後a[1]就是N-1個數的最小值)
以此類推,N-1次排序後,待排資料就已經按照從小到大的順序排列了。
直接選擇排序的java實現如下:
public static void selectionSort(int[] elements){for(int i = 0; i < elements.length-1; ++i){int k = i;for(int j = i; j < elements.length; ++j){if(elements[k] > elements[j]){k = j;}}if(k != i){//交換元素int temp = elements[i];elements[i] = elements[k];elements[k] = temp;}}}
直接選擇排序演算法的思路很清晰,實現起來也比較簡單,但是效率不是很高(O(n*n))。
堆排序演算法和直接選擇排序演算法最大的不同在於,堆排序演算法充分利用大頂堆和完全二叉樹的性質,保留每次排序後的結構,同時由於每次比較只是比較根節點和它的子節點,因此大大降低了比較的次數和交換的次數,從而提高效率,堆排序演算法的時間複雜度是O(nlogn,以2為底)。
堆排序演算法的思想是:(假設資料放在一個數組a中,且數組的長度是N)
1:以數組a為資料,建立一個大頂堆(這樣對於二叉樹的每個節點,根節點總是比子節點大,其實沒必要要求二叉樹的每個子樹也是大頂堆)
2:交換大頂堆的根節點和數組a中的最後一個節點(最後一個節點不在參與後邊的工作)
重複上邊的工作,經過N-1次後,數組a已經排好序。
堆排序演算法的java實現如下:
public static void heapSort(int[] elements){for(int i = elements.length-1; i > 0; i--){buildHeap(elements,i);//建堆swap(elements,0,i);//交換根節點和最後一個節點}}private static void buildHeap(int[] elements,int lastIndex){int lastParentIndex = (lastIndex-1)/2;//獲得最後一個父節點for(int i = lastParentIndex; i >=0; i--){int parent = elements[i];int leftChild = elements[i*2+1];//左節點肯定存在int rightChild = leftChild;if(i*2+2 <=lastIndex){rightChild = elements[i*2+2];//右節點不一定存在}int maxIndex = leftChild<rightChild?i*2+2:i*2+1;if(parent < elements[maxIndex]){swap(elements,i,maxIndex);}}}private static void swap(int[] elements,int firstIndex,int secondIndex){int temp = elements[firstIndex];elements[firstIndex] = elements[secondIndex];elements[secondIndex] = temp;}