這裏是傳送門⇒總結:關於排序算法html
平均時間複雜度 | 最優時間複雜度 | 最差時間複雜度 | 空間複雜度 | 穩定性 | |
---|---|---|---|---|---|
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不穩定 |
堆排序是一種利用「堆」數據結構而設計的排序算法。在升序序列中,利用的是「最大堆」,「最大堆」是「一棵任一父結點均大於或等於其子結點的徹底二叉樹」。算法
// 結點上浮:在插入二叉樹的最後一個位置時用到,此處沒有用到 // 此處的i是徹底二叉樹裏的順序,與數組裏的順序相比大了1 function MaxHeapShiftUp(array, i) { while (i / 2 >= 1) { var index = i - 1; var pIndex = Math.floor(i / 2) - 1; if (array[index] > array[pIndex]) { Swap(array, index, pIndex); } i = pIndex + 1; } } // 結點下沉 // 此處的i是徹底二叉樹裏的順序,與數組裏的順序相比大了1 // 此處傳入的array會被直接改變 function MaxHeapShiftDown(array, i, len) { while (i * 2 <= len) { var index = i - 1; var sIndex = i * 2 - 1; var max = sIndex; if (sIndex + 1 < len && array[sIndex] < array[sIndex + 1]) { max += 1; } if (array[index] < array[max]) { Swap(array, index, max); } i = max + 1; } } // 初始化堆 // 此處傳入的array會被直接改變 function BuildMaxHeap(array) { var len = array.length; for (var i = Math.floor(len / 2); i >= 1; i--) { MaxHeapShiftDown(array, i, len); } } // 此處傳入的array會被直接改變 function HeapSort(array) { var len = array.length; BuildMaxHeap(array); for (var i = len - 1; i > 0; i--) { Swap(array, 0, i); MaxHeapShiftDown(array, 1, --len); } }
爲何建堆的時候(即BuildMaxHeap函數中),最後一個非葉子結點是Math.floor(len / 2)
?緣由看這個筆記:關於徹底二叉樹數組
// 這個是遞歸的作法 // 此處的i是徹底二叉樹裏的順序,與數組裏的順序相比大了1 function MaxHeapShiftDown_v2(array, i, len) { var left, right, max; max = left = 2 * i; if (left > len) { return; } right = left + 1; if (right < len && array[right] > array[left]) { max = right; } if (array[i] < array[max]) { Swap(array, i, max); MaxHeapShiftDown_v2(array,max,len); } }
MaxHeapShiftDown
函數的時間複雜度爲O(logn)Math.floor(n / 2)
次MaxHeapShiftDown
函數,因此建堆的時間複雜度爲O(nlogn)Math.floor(n / 2) + n - 1
次MaxHeapShiftDown
函數的時間,即堆排序的時間複雜度爲 O(nlogn)