堆排序可以分為兩個階段。在堆的構造階段中,我們將原始陣列重新組織安排進乙個堆中;然後在下沉排序階段,我們從堆中按遞減順序取出所有元素並得到排序結果。
堆的構造:從右至左用sink()函式構造子堆。陣列的每個位置都已經是乙個子堆的根結點了,sink()對於這些子堆也適用。如果乙個結點的兩個子結點都已經是堆了,那麼在該結點上呼叫sink()可以將它們變成乙個堆。這個過程會遞迴地建立起堆的秩序。開始時我們只需要掃瞄陣列中的一半元素,因為我們可以跳過大小為1的子堆。最後我們在位置1上呼叫sink()方法,掃瞄結束。
下沉排序:堆排序的主要工作都是在第二階段完成的。這裡我們將堆中的最大元素刪除,然後放入堆縮小後陣列中空出的位置。
package section2_1.priorityqueue;
public
class
heap
private
void
exch
(comparable[
] a,
int i,
int j)
private
void
sink
(comparable[
] a,
int k,
int n)
}public
void
sort
(comparable[
] a)
while
(n>1)
}public
static
void
main
(string[
] args)
; heap h =
newheap()
; h.
sort
(s);
for(
int i=
1;i}
這個程式的堆排序中迴圈任務各不同,第一段迴圈構造堆,第二段迴圈在下沉排序中銷毀堆,它們都是基於sink()方法。
排序軌跡:
堆排序在排序複雜性的研究中有著重要的地位,因為它是我們所知的唯一能夠同時最優地利用空間和時間的方法——在最壞的情況下它也能保證適用~2nlgn次比較和恆定的額外空間。當空間十分緊張的時候它很流行,因為它只用幾行就能實現較好的效能。但現代系統的許多應用很少使用它,因為它無法利用快取。陣列元素很少和相鄰的其它元素進行比較,因此快取未命中的次數要遠遠高於大多數比較都在相鄰元素間進行的演算法,如快速排序、歸併排序,甚至是希爾排序。
另一方面,用堆實現的優先佇列在現代應用程式中越來越重要,因為它能在插入操作和刪除最大元素操作混合的動態場景中保證對數級別的執行時間。
alg4 排序 歸併排序
歸併操作 即將兩個有序的陣列歸併成乙個更大的有序陣列。歸併排序示意圖 歸併排序最吸引人的性質是它能夠保證將任意長度為n的陣列排序所需時間和nlogn成正比 它的最主要缺點則是它所需的額外空間和n成正比。原地歸併的抽象方法 它將涉及的所有元素複製到乙個輔助陣列中,再把歸併的結果放回原陣列中。merge...
JS演算法4 排序 堆排序
堆 是乙個近似完全二叉樹的結構,並同時滿足堆積的性質 即子結點的鍵值或索引總是小於 或者大於 它的父節點。堆排序 是指利用堆這種資料結構所設計的一種排序演算法 heapinsert arr,index 增大堆結構 先建立大根堆,這是乙個往上走的過程,進來的元素與父元素比,大了就往上走,此時陣列仍為無...
18 排序 堆排序
void selection sort elementtype a,int n 中找到最小元,並將其位置賦給minposition minposition scanformin a,i,n 1 將未排序部分的最小元換到有序部分的最後位置 swap a i a minposition 時間複雜度 t ...