一種支援刪除最大元素和插入元素兩種操作的資料結構叫做優先佇列。
實現棧or佇列與實現優先佇列的最大不同在於效能的要求。對於棧和佇列,我們實現能在常數時間完成所有操作;而優先佇列,插入元素和刪除最大元素這兩個操作在最壞情況下需要線性時間完成
優先佇列的各種實現在在最壞情況下執行時間的增長數量級
資料結構
插入元素
刪除最大元素
有序陣列n1
無序陣列1n
堆logn
logn
理想情況11
資料結構二叉堆可以很好地實現優先佇列的基本操作。在二叉堆的陣列中,每個元素都要保證大於等於另兩個特定位置的元素。二叉堆是一組能夠用堆有序的完全二叉樹排序的元素,並在陣列中按照層級儲存(不使用陣列的第乙個位置)
在乙個堆中,位置k的結點的父結點的位置為floor(k/2),它的兩個子結點的位置分別為2k和2k+1。一棵大小為n的完全二叉樹的高度為floor(lgn)
由下至上的堆有序化(上浮)
如果堆有序因為某個結點變的比它的父節點更大而打破,那麼我們就需要通過交換它和它的父節點來修復堆。交換後,仍然可能比現在的父節點大,那麼就繼續交換,直到遇到比自身更大的父結點。只要記住位置k的父結點的位置是floor(k/2)
void
swim
(int k)
}
由上至下的堆有序化(下沉)
如果堆有序的狀態因為某個結點變的比它的兩個子結點或是其中之一更小而被打破了,那麼我們可以通過將它和它的子結點中的較大者交換來修復堆。直到向下移動到它的子結點都比它更小or到達了堆的底部。只要記住位置為k的子結點位於2k和2k+1。
void
sink
(int k)
}
插入元素
我們將新元素加到陣列末尾,增加堆的大小並讓這個新元素浮到適合位置
void
insert
(int v)
刪除最大元素
我們從陣列頂端刪去最大的元素,並將陣列的最後乙個元素放到頂端,減小堆的大小並讓這個元素下沉到合適的位置。
int
delmax()
它對優先佇列的實現可以保證插入元素和刪除最大元素這兩個操作的用時和佇列的大小僅成對數關係。
堆排序可以分為兩個階段。在堆的構造階段,我們將原始陣列重新組織安排進乙個堆裡;然後在下沉排序階段,我們從堆中安地基按順序取出所有元素並的倒排序結果。
可以在nlogn成正比的時間完成構造,只要從左到右遍歷陣列,用swim()保證指標左側的所有元素已經是一棵堆有序的完全樹即可。
但是有乙個更聰明更高效的方法就是從右至左用sink()函式構造子堆。陣列的每個位置都已經是乙個子堆的根結點了,sink()對這些子堆也是用。
用sink操作構造n個元素的堆只需少於2n次比較以及少於n次交換
void
sort
(vector<
int> a)
}
for迴圈構造了堆,然後while迴圈將最大的元素a[1]和a[n]交換並修復了堆。
堆排序的主要工作都是在第二階段完成的,這裡我們將堆中最大元素刪除,然後放入堆縮小後陣列中空出的位置。這個過程和選擇排序很類似,但所需要的比較少很多次。
堆排序只需最少2nlgn+2n次比較,以及一半次數的交換。
2n項來自堆的構造。2nlgn來自每次下沉操作可能需要2lgn次比較,然後有n個元素
總的來說,堆排序
時間複雜度o(nlogn)
不穩定!!
堆排序 優先佇列
1.堆排序 a.堆的定義 n個元素序列當且僅當滿足以下關係時,稱之為堆。ki k2i且ki k2i 1 小根堆 ki k2i且ki k2i 1 大根堆 以下針對最大堆 b.維護堆的性質 max heapify通過讓a i 的值在最大堆中 逐級下降 a i 的值小於其左右孩子的值時 從而使得以i為根結...
堆排序 最大優先佇列
優先佇列支援的操作 insert maximum,extract,increasekey,include include include define number 100 define num 6 using namespace std struct heaptype void exchange ...
優先佇列與堆排序
許多應用程式在資料處理是,需要有序的處理資料,但是不一定要求他們全部有序,或著是不一定要一次就將整個資料進行排序。例如有些我們收集了一些元素,然後處理這些元素中的最大值。這個時候,對這兒陣列進行排序沒有必要,這就引出我們今天介紹的優先佇列。優先佇列時一種抽象資料型別,其最重要的操作就是刪除最大元素和...