// 待調整的堆 要下沉的父節點 堆的有效大小 function downAdjust (array, parentIndex, length) { // temp 保存父節點的值 用於最後的賦值 var temp = array[parentIndex] var childIndex = 2 * parentIndex + 1 // 左孩子下標 while (childIndex < length) { // 若是有右孩子,且右孩子大於左孩子的值 則定位到右孩子 if(childIndex + 1 < length && array[childIndex + 1] > array[childIndex]) { childIndex++ } // 若是父節點大於任何一個孩子的值,則直接跳出 if (temp >= array[childIndex]) { break } // 無需真正交換 單向賦值便可 由於比較尚未結束 // 父節點下面的子節點還會可能有子節點 須要接着比較 因此不能直接將父子節點的值直接交換 array[parentIndex] = array[childIndex] // 子節點中值大的上浮 parentIndex = childIndex // 子節點的索引賦給父節點索引 childIndex = 2 * childIndex + 1 // 計算子節點有沒有子節點 沒有值會超出length 本次循環結束 } array[parentIndex] = temp // 在這裏將原來父節點的值替換到子節點中 parentIndex是原來值大子節點的索引 } function heapSort (array) { // 把無序數組構建成最大堆 // 從最後一個非葉子節點開始 依次比較 // Math.ceil((array.length-2)/2)最後一個非葉子節點的下標 for (var i = Math.ceil((array.length-2)/2); i >= 0; i--) { downAdjust(array, i, array.length) } // 循環調整堆頂元素 移到集合尾部 調整堆產生新的堆頂 // 最大堆堆頂是堆中最大的元素,第一次直接將該元素和第一個元素調換位置,將除最後一個元素外的剩下元素再構建成最大堆,這樣第二輪中第二大的元素就會成爲堆頂,而後將第二大元素與倒數第二個元素交換位置,以此類推。數組最後就會成爲升序數組 for (var i = array.length-1; i > 0; i--) { // 最後一個元素和第一個元素進行交換 var temp = array[i] array[i] = array[0] array[0] = temp // 除去已經調整的元素,將剩下的元素從新調整爲最大堆 downAdjust(array, 0, i) } return array } var arr = [1,3,2,6,5,7,8,9,10,0] console.log(heapSort(arr))