排序 選擇排序(直接選擇排序 堆排序)

2021-06-21 12:04:40 字數 3411 閱讀 3542

選擇排序(selection sort)的基本思想是:每一趟從待排序的記錄中選出關鍵字最小的記錄,順序放在已排好序的子檔案的最後,直到全部記錄排序完畢。

常用的選擇排序方法有

直接選擇排序

和堆排序。

直接選擇排序(straight selection sort)

1、直接選擇排序的基本思想

n個記錄的檔案的直接選擇排序可經過n-1趟直接選擇排序得到有序結果:

①初始狀態:無序區為r[1..n],有序區為空。

②第1趟排序

在無序區r[1..n]中選出關鍵字最小的記錄r[k],將它與無序區的第1個記錄r[1]交換,使r[1..1]和r[2..n]分別變為記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。

……③第i趟排序

第i趟排序開始時,當前有序區和無序區分別為r[1..i-1]和r[i..n](1≤i≤n-1)。該趟排序從當前無序區中選出關鍵字最小的記錄r[k],將它與無序區的第1個記錄r[i]交換,使r[1..i]和r[i+1..n]分別變為記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。

這樣,n個記錄的檔案的直接選擇排序可經過n-1趟直接選擇排序得到有序結果。

2、直接選擇排序的過程

【參見動畫演示

】3、演算法描述

直接選擇排序的具體演算法如下:

void selectsort(seqlist r)

)我們把堆看成一棵完全二叉樹(其實就是),其任何一非葉節點滿足性質:

(1)ki≤k

2i且ki≤k

2i+1

或(2)ki≥k

2i且ki≥k

2i+1    

(1≤i≤

(n/2)

)即任何一非葉節點的關鍵字不大於或者不小於其左右孩子節點的關鍵字。

【例】關鍵字序列(10,15,56,25,30,70)和(70,56,30,25,15,10)分別滿足堆性質(1)和(2),

故它們均是堆,其對應的完全二叉樹分別如小根堆示例和大根堆示例所示。

2、大根堆(序列遞增)和小根堆(遞減)

根結點(亦稱為堆頂)的關鍵字是堆裡所有結點關鍵字中最小者的堆稱為小根堆。

根結點(亦稱為堆頂)的關鍵字是堆裡所有結點關鍵字中最大者,稱為大根堆。

注意:①堆中任一子樹亦是堆。

②以上討論的堆實際上是二叉堆(binary heap),類似地可定義k叉堆。

3、大根堆思想(小根堆請自行分析)

(1)假設現有乙個r[1....n]的大根堆(無序區是r[1...n],沒有有序區),根據大根堆的性質,我們知道r[1].key是最大的。

所以我們做一下操作:

① 將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]構造為堆。

最後,對於堆排序,最重要的兩個操作就是

構造初始堆

和調整堆

,其實構造初始堆事實上也是調整堆的過程,只不過

構造初始堆是對所有的非葉節點都進行調整

。注意:在任何時刻,堆排序中無序區總是在有序區之前,且有序區是在原向量的尾部由後往前逐步擴大至整個向量為止。

下面舉例說明:

給定乙個整形陣列a=,對其進行堆排序。

首先根據該陣列元素構建乙個完全二叉樹,得到

然後需要構造初始堆,則從最後乙個非葉節點開始調整(8->7->16),調整過程如下:

20和16交換後導致16不滿足堆的性質,因此需重新調整

即每次調整都是從父節點、左孩子節點、右孩子節點三者中

選擇最大者

跟父節點進行交換(交換之後可能造成被交換的孩子節點不滿足堆的性質,因此每次交換之後要重新對被交換的孩子節點進行調整)。有了初始堆之後就可以進行排序了。

從上述過程可知,堆排序其實也是一種選擇排序,是一種樹形選擇排序。只不過直接選擇排序中,為了從r[1...n]中選擇最大記錄,需比較n-1次,然後從r[1...n-2]中選擇最大記錄需比較n-2次。事實上這n-2次比較中有很多已經在前面的n-1次比較中已經做過,而樹形選擇排序恰好利用樹形的特點儲存了部分前面的比較結果,因此可以減少比較次數。

(3)堆排序的演算法:

//對r[1..n]進行堆排序,r[0]做暫存單元

void heapsort(heaptype& r)

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

//endfor

} //heapsort

(4)堆調整演算法:

//調整堆,r是資料型別,s是要調整的結點,m是無序區的最後一位

void heapadjust(heaptype& r,int s,int m)

r[s] = r[0]; //最後,插入真確位置

}

5、大根堆排序例項【

動畫演示】。

6、 演算法分析

堆排序的時間,主要由建立初始堆和反覆重建堆這兩部分的時間開銷構成。

堆排序的最壞時間複雜度為o(nlgn)。堆排序的平均效能較接近於最壞效能。

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

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

它是不穩定的排序方法。

部分資源摘自

選擇排序 直接選擇排序,堆排序

選擇排序 selection sort 是一種簡單直觀的 排序演算法 它的工作原理是每一次從待排序的 資料元素 中選出最小 或最大 的乙個元素,存放在序列的起始位置,直到全部待排序的資料元素排完。選擇排序是不穩定的排序方法 1.簡單的選擇排序 基本思想 在要排序的一組數中,選出最小的乙個數與第乙個位...

選擇排序 直接選擇排序 堆排序

1.基本思想 每一次從待排序的資料元素中選出最小 或最大 的乙個元素,存放在序列的起始位置,直到全部待排序的資料元素排完 在元素集合array i array n 1 中選擇關鍵碼最大 小 的資料元素 若它不是這組元素中的最後乙個 第乙個 元素,則將它與這組元素中的最後乙個 第乙個 元素交換 在剩餘...

選擇排序(直接選擇排序 堆排序)

選擇排序的基本方法 每次都從待排序物件中選出排序碼最大或最小的物件,依次排列,一共進行n 1次即可將n個物件排序完成。選擇排序的實施方案 1.直接選擇排序 2.堆排序 一 直接選擇排序 1.演算法 直接選擇排序 func selectsort data int if minindex i 2.時間複...