1、前言
在了解堆排序之前,需要知道堆的一些特徵,那就是堆就是乙個完全二叉樹,所以需要了解完全二叉樹的特點
完全二叉樹的特點:
(1)葉子節點只能在最大的兩層出現
(2)如果i=1,結點就是根結點,如果i>1,則其雙親parent(i)=i/2
(3)如果2i>n,則結點無左孩子,如果2i+1>n,則結點無右孩子
(4)如果下標從0開始,則第乙個非葉子結點的下標為 length/2-1
堆排序會用到大頂堆和小頂堆,公升序排序時用大頂堆,降序排序時用小頂堆。大頂堆的特點是節點值大於其左右孩子節點值,即value(n)>=value(n->left)並且value(n)>=value(n->right),小頂堆相反
2、穩定性、時間複雜度、空間複雜度
堆排序為什麼不穩定:因為構建大頂堆/小頂堆的時間不穩定
平均時間複雜度:o(n*logn)
空間複雜度幾乎為0(只用到幾個臨時變數)
3、具體思路(以公升序、大頂推為例,陣列小標為0,長度為length)
(1)構建初始堆(或者叫調整堆結構,就是將乙個陣列構建成乙個標準堆結構)
選取第乙個非葉子節點,資料下標為length/2-1,倒序遍歷整個陣列,將堆元素按自下到上的順序,將最大的數字交換到堆頂,構建大頂堆。為什麼初始化堆時要選取第乙個非葉子節點呢?以及為什麼第乙個非葉子節點的下標為length/2-1呢?對於完全二叉樹(n層)第乙個非葉子節點在n-1層,因為需要將最大的元素通過拉的方式拉倒堆頂,所以肯定從n-1層開始拉,並且只有父節點需要做這個工作,所以從最後乙個父節點開始拉。因為完全二叉樹每個父節點(下標i)的孩子左節點下標為2i+1右孩子2i+2,假設只有左孩子則length為偶數,此時2i+1=length-1,即i=length/2-1。假設有右孩子則length為奇數,此時2i+2=length-1,即i=(length-1)/2-1,由於整數的除法是向下取整,(length-1)/2=length/2,所以i=length/2-1
(2)將堆頂元素與陣列最後乙個元素交換,此時最大的元素在陣列最後面
(3)將陣列0到length-2之間的元素繼續調整為堆結構,然後交換下標0和length-2的元素值 ,繼續調整 0到length-3的之間的資料元素,直到所有元素都有序
4、**
package api
//sortbyheap 堆排序
func sortbyheap(arr int, length int, desc bool) else
} //交換、再調整
for j := length - 1; j >= 0; j-- else }}
//構建乙個大頂堆
func adjustbigheap(arr int, i int, length int)
if arr[k] > temp else
} arr[i] = temp
}//構建乙個小頂堆
func adjustsmallheap(arr int, i int, length int)
if arr[k] < temp else
} arr[i] = temp
}
go 排序演算法 堆排序
1.5 堆排序 堆排序 heapsort 是指利用堆這種資料結構所設計的一種排序演算法。堆積是乙個近似完全二叉樹的結構,並同時滿足堆積的性質 即子結點的鍵值或索引總是小於 或者大於 它的父節點。核心思路 1 depth length 2 1 節點深度,n,2n 1,2n 2 2 遞迴思想,找出最大值...
go的堆排序
堆的概念 堆是一種圖的樹狀結構,被用於實現 優先佇列 1.首先建立堆 堆的特性 1 完全二叉樹 2 每乙個節點都大於其左右子節點 3 根節點最大 大堆 4 左子節點2i 1,由子節點2i 2,父節點 i 1 2 package main import fmt func parentnode i in...
go 多重排序 堆排序
記錄一下go實現多重排序的方法和實現堆排序的方式 實現sort介面即可用sort.sort 方法對物件進行排序,而多重排序呢,我想傳入不同排序規則,然後讓該物件依次執行不同規則 排序規則 type lessfunc func p1,p2 curriculumelem bool multisorter...