swift演算法之排序 (四)堆排序

2021-09-23 23:45:58 字數 2441 閱讀 8474

1、概述

堆排序是指利用堆這種資料結構所設計的一種排序演算法。

堆是乙個近似完全二叉樹,並同時滿足堆積的性質:子節點的鍵值或索引總是大於/小於它的父結點。

堆又分為 大頂堆 和小頂堆,大頂堆的特點是 該完全二叉樹的根節點比其左右節點都要大,小頂堆的特點是 在小頂堆中根節點比左右子節點的值都要小。

1)大頂堆

假設根節點的編號是 i ,那麼該根節點的左孩子的編號是 2i,右孩子的編號是 2i+1。

根節點和子節點的關係為:k(i)>=k(2i)、k(i)>=k(2i+1) i>=1

2)小頂堆

假設根節點的編號是 i ,那麼該根節點的左孩子的編號是 2i,右孩子的編號是 2i+1。

根節點和子節點的關係為:k(i)<=k(2i)、k(i)<=k(2i+1) i>=1

2、演算法原理

思想:將無序的序列構建成大頂堆/小頂堆,最後將排好序的堆轉換成大頂堆/小頂堆的層次遍歷的序列,即為所求

步驟:1)最大堆調整max_heapify:將堆的末端子節點作調整,使得子結點永遠小於父結點,其目的是保持最大堆的性質,是建立最大堆的核心子程式

2)建立最大堆build_max_heap:將堆所有資料重新排序。其目的是將乙個陣列改造成最大堆,接受陣列和堆大小兩個引數,build-max-heap 將自下而上的呼叫 max-heapify 來改造陣列,建立最大堆

3)堆排序heapsort:移除位在第乙個資料的根節點,並做最大堆調整的遞迴運算

3、舉例

以 [62, 88, 58, 47, 62, 35, 73, 51, 99, 37, 93]為例

1)先將上述序列從左往右存入完全二叉樹中

2)構建 大頂堆

(1)先對子樹進行調整,將其調整為大頂堆。找到完全二叉樹最下方最小的以62為根節點的子樹,先比較62的兩個節點,93最大,由於62<93,所以交換62與93的位置。該子樹的大頂堆構建完成

(2)以(1)的方式調整以47為根節點的子樹,調整完成後,再分別調整以88和58為根節點的子樹

(3)對整棵樹進行調整,最終大頂堆構建完成

3)對大頂堆進行排序

(1)將大頂堆的第乙個值(整個序列中最大的值)與大頂堆的最後乙個值進行交換。

(2)交換後,最後乙個值作為整個序列中最大值,將此值從大頂堆中剔除,再將剩下的元素再次進行調整為大頂堆。

4、演算法實現

從小到大的排序思路:把一堆數字調整成大頂堆->堆頂元素和末尾元素交換->去掉末尾元素,繼續大頂堆調整->重複以上動作

堆是通過陣列實現的:

1)父結點i的左子節點的位置---(2*i+1)

2)父結點i的右子節點的位置---(2*i+2)

3)子結點i的父結點的位置---floor((i-1)/2)  floor函式的作用是向下取整

func heapsort(_ array : inout array)

//2、調整堆結構+交換堆頂元素與末尾元素

for j in (1...(array.count-1)).reversed()

}//調整大頂堆(僅是調整過程,建立在大頂堆以構建的基礎上)

func adjustheap(_ array : inout array, _ i : int, _ length : int)else

//下乙個結點

k = k*2+1

}//將tmp值放到最終的位置

array[i] = tmp

}

5、時間複雜度1)在構建堆的過程中,由於是是完全二叉樹從最下層最右邊非終端節點開始構建,將它與子節點進行比較,對於每個非終端節點而言,最多進行兩次比較和交換操作,因此構建堆的時間複雜度為o(n)

2)在整個排序過程中,第 i 次去堆頂記錄重建堆需要時間為logi ,並且需要取 n - 1次堆記錄,所以重建堆的時間複雜度為o(nlogn)。

3)堆的時間複雜度為o(nlogn)

github**

注:排序的具體實現**在 sortsummary.swift 檔案裡 呼叫是在 viewcontroller.swift

排序演算法 (四)堆排序

對簡單選擇排序的優化。1 將序列構建成大頂堆。2 將根節點與最後乙個節點交換,然後斷開最後乙個節點。3 重複第 一 二步,直到所有節點斷開。堆排序模擬流程圖 public class heapsort 對data陣列從0到lastindex建大頂堆 private static void build...

排序演算法(四)堆排序

堆排序 是指利用堆積樹 堆 這種資料結構所設計的一種排序演算法,它是選擇排序的一種。堆的定義 乙個完全二叉樹中,任意父結點總是大於或等於 小於或等於 任何乙個子節點,則為大頂堆 小頂堆 完全二叉樹適合採用順序儲存的方式,因此乙個陣列可以看成乙個完全二叉樹。先將初始檔案r n 建立成乙個大頂堆 小頂堆...

八大排序(四) 堆排序

堆是具有以下性質的完全二叉樹 每個結點的值都大於或等於其左右孩子結點的值,稱為大頂堆 每個結點的值都小於或等於其左右孩子結點的值,稱為小頂堆 如下圖所示 對堆中的結點按層進行編號,將這種邏輯結構對映到陣列中就是下面這個樣子 以上陣列從邏輯上講就是乙個堆結構,用簡單的公式來描述一下堆的定義就是 大頂堆...