堆排序是一種時間複雜度在o(n
lnn)
o(n\ln n)
o(nlnn)
的排序方式
它利用了一種叫"堆"的資料結構
此「堆」非彼「堆」,和記憶體裡面的「堆」、「棧」是不一樣的。它是一種基於二叉樹的資料結構
堆的特點是,根結點是子節點的最大值或者最小值
子節點的最值全部都堆在根結點上了,所以這個資料結構叫堆(強行自圓其說)
介紹一下使用陣列模擬二叉樹構造堆的方法
為什麼要使用陣列模擬呢?因為在實際的使用中陣列比鍊錶更加方便,我不希望為了給幾個元素進行排序而寫幾十行**來構建乙個鍊錶,也不希望大部分時間都耗費在申請記憶體和等待之中。
要使用陣列進行二叉樹模擬,首先要對二叉樹的結構有清晰的認識
以下是幾個會用得到的性質:
完全二叉樹:最下面兩層結點的degree可以小於2,最後一層葉節點集中在左邊位置上。顯然我們需要構建完全二叉樹
根結點i
的子節點為2i+1
與2i+2
深度為k
kk的二叉樹至多有2∗k
−12*k-1
2∗k−
1個節點
構建乙個根結點是子節點的最大值(僅以最大值為例)
可以使用遞迴方法
void
maxheapify
(int
*arr,
int start,
int end)
使用非遞迴方法速度更快:
void
maxheapify
(int
*arr,
int start,
int end)
}
在構造好堆後,因為每乙個子樹的根結點都是這個子樹裡最大的元素
因此,我們得出了根結點是最大的元素的結論
而第二大的元素和第三大的元素分別存放在根結點的左右子葉中,順序不固定
在構造好了堆這個結構後,我們有了新的想法:
既然堆這個結構中,最大的元素必然在根結點處,那麼,我把根結點和最後乙個節點進行交換,最後乙個節點處就必然是最大的元素了
此時,我再把最後的乙個節點排除在堆外,重建好堆後,然後再次重複上面這個過程,每次都可以將最大的元素放置到最後乙個節點處
當堆裡面沒有元素可以再排除的時候,陣列就可以構建完畢了
void
heapsort
(int
*arr,
int size)
}
對該演算法進行測試。規模為1000~100000,步長為1000
測試結果圖如下
排序演算法 堆排序
1 什麼是堆 首先它是一顆完全二叉樹,並且父結點的值大於子節點的值 最大堆 或父結點的值小於子結點的值 最小堆 小根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最小者的堆稱為小根堆,又稱最小堆。大根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最大者,稱為大根堆,又稱最大堆。2 堆...
排序演算法 堆排序
花了一晚上時間研究堆排序,這個排序困擾了哥很久,終於搞清楚了。一 堆的定義 1.父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值 2 每個結點的左子樹和右子樹都是乙個二叉堆 都是最大堆或最小堆 二 已知結點 i 則它的子結點 為2 i 1 與 2 i 2 父節點為 i 1 2 三 堆排序...
排序演算法 堆排序
由於不經常使用,之前學習看過的演算法都給忘了。現在把他們寫下來,記錄下來,以方便以後查閱。本篇文章的 即為堆排序的 主函式中是對輸入檔案中的序列進行排序,並將結果輸出到乙個檔案中。這是一種形式類似於google codejam的測試方法。include include using namespace...