【java面試】演算法篇之堆排序
阿新 • • 發佈:2019-01-02
一、堆的概念
堆是一棵順序儲存的完全二叉樹。完全二叉樹中所有非終端節點的值均不大於(或不小於)其左、右孩子節點的值。
其中每個節點的值小於等於其左、右孩子的值,這樣的堆稱為小根堆;
其中每個節點的值大於等於其左、右孩子的值,這樣的堆稱為大根堆;
二、要點
1.將陣列構造成初始堆(若想升序則建立大根堆,若想降序,則建立小根堆)
從最後一個節點開始調整,得到初始堆。
2.堆排序處理
交換堆頂的元素和最後一個元素,此時最後一個位置作為有序區(有序區顯示為黃色),然後進行其他無序區的堆調整,重新得到大頂堆後,交換堆頂和倒數第二個元素的位置……
重複此過程:
最後,有序擴充套件完成即排序完成:
核心程式碼
public void HeapAdjust(int[] array, int parent, int length) { int temp = array[parent]; // temp儲存當前父節點 int child = 2 * parent + 1; // 先獲得左孩子 while (child < length) { // 如果有右孩子結點,並且右孩子結點的值大於左孩子結點,則選取右孩子結點 if (child + 1 < length && array[child] < array[child + 1]) { child++; } // 如果父結點的值已經大於孩子結點的值,則直接結束 if (temp >= array[child]) break; // 把孩子結點的值賦給父結點 array[parent] = array[child]; // 選取孩子結點的左孩子結點,繼續向下篩選 parent = child; child = 2 * child + 1; } array[parent] = temp; } public void heapSort(int[] list) { // 迴圈建立初始堆 for (int i = list.length / 2; i >= 0; i--) { HeapAdjust(list, i, list.length - 1); } // 進行n-1次迴圈,完成排序 for (int i = list.length - 1; i > 0; i--) { // 最後一個元素和第一元素進行交換 int temp = list[i]; list[i] = list[0]; list[0] = temp; // 篩選 R[0] 結點,得到i-1個結點的堆 HeapAdjust(list, 0, i); System.out.format("第 %d 趟: \t", list.length - i); printPart(list, 0, list.length - 1); } }
演算法分析
堆排序演算法的總體情況
排序類別 |
排序方法 |
時間複雜度 |
空間複雜度 |
穩定性 |
複雜性 |
||
平均情況 |
最壞情況 |
最好情況 |
|||||
選擇排序 |
堆排序 |
O(nlog2n) |
O(nlog2n) |
O(nlog2n) |
O(1) |
不穩定 |
較複雜 |