演算法三之堆排序

2022-07-20 15:24:12 字數 1614 閱讀 2380

(1)n個關鍵字序列kl,k2,…,kn稱為(heap),當且僅當該序列滿足如下性質(簡稱為堆性質):

k(i)<=k(2i)且k(i)<=k(2i+1)(1≤i≤ n/2),

當然,這是小根堆,大根堆則換成》=號。

(2)k(i)相當於二叉樹的非葉子結點,k(2i)則是左子節點,k(2i+1)是右子節點

若將此序列所儲存的向量r[1..n]看做是一棵完全二叉樹的儲存結構,則堆實質上是滿足如下性質的完全二叉樹:

樹中任一非葉子結點的關鍵字均不大於(或不小於)其左右孩子(若存在)結點的關鍵字。

堆排序利用了大根堆(或小根堆)堆頂記錄的關鍵字最大(或最小)這一特徵,使得在當前無序區中選取最大(或最小)關鍵字的記錄變得簡單。

(1)用大根堆排序的基本思想

① 先將初始檔案r[1..n]建成乙個大根堆,此堆為初始的無序區

② 再將關鍵字最大的記錄r[1](即堆頂)和無序區的最後乙個記錄r[n]交換,由此得到新的無序區r[1..n-1]和有序區r[n],且滿足r[1..n-1].keys≤r[n].key

③由於交換後新的根r[1]可能違反堆性質,故應將當前無序區r[1..n-1]調整為堆。然後再次將r[1..n-1]中關鍵字最大的記錄r[1]和該區間的最後乙個記錄r[n-1]交換,由此得到新的無序區r[1..n-2]和有序區r[n-1..n],且仍滿足關係r[1..n-2].keys≤r[n-1..n].keys,同樣要將r[1..n-2]調整為堆。

……直到無序區只有乙個元素為止。

/**

* 堆排序

* @param

data 資料佇列

*/public

static

void heapsort(int

data)

int temp; //

臨時空間

for (int i = data.length - 1; i > 0; i--)

}/*** 堆調整

* @param

data 資料佇列

* @param

start 起始位置

* @param

end 截止位置,是堆尾的下乙個位置

*/public

static

void adjustheap(int data, int start, int

end)

//起始位置值最大

if(src >= data[i])

break

;

data[start]=data[i];//

賦值最大值

start=i; //

記錄大值的位置

} data[start]=src;//

回填起始值

}

堆排序的時間,主要由建立初始堆和反覆重建堆這兩部分的時間開銷構成,它們均是通過呼叫adjustheap實現的。

平均效能o(n*logn),

由於建初始堆所需的比較次數較多,所以堆排序不適宜於記錄數較少的檔案。

堆排序是就地排序,輔助空間為o(1).

它是不穩定的排序方法。(排序的穩定性是指如果在排序的序列中,存在前後相同的兩個元素的話,排序前 和排序後他們的相對位置不發生變化)

演算法三之堆排序

一 堆 heap 定義 1 n個關鍵字序列kl,k2,kn稱為 heap 當且僅當該序列滿足如下性質 簡稱為堆性質 k i k 2i 且k i k 2i 1 1 i n 2 當然,這是小根堆,大根堆則換成 號。2 k i 相當於二叉樹的非葉子結點,k 2i 則是左子節點,k 2i 1 是右子節點 若...

演算法 排序演算法之堆排序

package sortarith 堆排序 構建最大堆,堆頂即為最大元素,每次取出最大元素後,再重新構建堆,這樣再拿出次大值,迴圈往返 注意 構建堆時需要調整每個非葉子節點,確定其為子堆的最大值 而調整堆時,只需要調整堆頂元素 特例1 若所給待排序陣列array本身已是最大堆型別,可不進行構建堆,即...

演算法 排序演算法之堆排序

堆排序 heapsort 是指利用堆這種資料結構所設計的一種排序演算法。堆積是乙個近似完全二叉樹的結構,並同時滿足堆積的性質 即子結點的鍵值或索引總是小於 或者大於 它的父節點。堆排序可以說是一種利用堆的概念來排序的選擇排序。分為兩種方法 大頂堆 每個節點的值都大於或等於其子節點的值,在堆排序演算法...