使用 Swift 實現堆排序

2021-09-11 11:16:18 字數 2786 閱讀 3460

排序是計算機的一項主要任務。這並不是因為排序本身非常有趣,而是因為很多其它演算法依賴於排序才能正常執行。本文主要描述如何實現堆排序演算法,該演算法依賴於稱為堆的資料結構。

本文的具體實現可以檢視對應的 xcode playground 檔案。

堆是乙個完整且部分排序的二叉樹。通俗一點講就是它總是將新資料節點插入最深一層的左側。從某種意義上講,元素間是有順序的,儘管實際上並未做排序操作。

在本教程中,我們將使用最大堆(max heap)實現乙個始終在 o(n * log(n)) 時間內執行的排序演算法。首先,我們將實現乙個sortingalgorithms類,該類帶有乙個對陣列進行排序的靜態函式,然後再使用面向協議的解決方案。

關於最大堆,有三個重要事項:

首先,我們來擴充套件 swift 標準庫的 int 型別的實現,以抽象出獲取父節點和子節點索引的運算公式。如下**所示:

private

extension

int

var leftchild: int

var rightchild: int

}複製**

使用這些**,我們可以通過計算屬性來計算索引,而不是需要時直接用數學公式來計算。這樣保證了可讀性。另外這是乙個私有擴充套件,意味著它不會影響 int 的整體性,而只是在該檔案作用域中可用。

接下來,讓我們分步來說明排序演算法的各個步驟。

首先,我們將從陣列構建乙個最大堆。基本操作是將新元素插入到堆的末尾再交換到正確的位置,因此我們可以使用簡單的迴圈來模擬插入操作。我們先假定陣列只有兩個元素,「堆積」這兩個元素,在迴圈的每個迭代中,我們插入乙個元素並重新堆積。如下所示:

操作完成後,陣列看上去並沒有特意排序。事實上,看起來更糟糕。這是因為我們使用陣列儲存了樹的節點。看一下操作前後的對比:

看上去我們只是交換了元素,但事實上,我們剛剛建立了乙個將用於完成排序的屬性。

獲取第乙個元素,然後將其與最後乙個元素交換,我們可以把最大的元素放到最後。然後假定陣列長度減 1,然後重新堆積這個子陣列,又可以得到這個子陣列的最大元素。然後將子陣列的最大元素放到子陣列最後,這樣依此類推,就可以得到乙個完全排序的陣列。

我們的 .heapsort(_:) 方法的**如下,包括構建和縮小堆。

class

sortingalgorithms

public

static

func

heapsort

(_ array: inout [datatype])

buildheap(&array)

shrinkheap(&array)

} private

static

func

buildheap

(_ array: inout [datatype])

}}

private

static

func

shrinkheap

(_ array: inout [datatype])

else

if rightchild < index && array[rightchild] > array[maxchild]

guard array[maxchild] > array[parent] else

swap(parent, with: maxchild, in: &array)

parent = maxchild

leftchild = parent.leftchild

rightchild = parent.rightchild}}

} private

static

func

swap

(_ firstindex: int, with secondindex: int, in array: inout [datatype]) }

複製**

這就是我們想要的,不過我們可以讓它更乾淨一些。

通過擴充套件可比較元素型別的 array 型別,我們能得到一些好處。乙個是**量更少,另乙個是可以直接在物件上呼叫方法,而不需要如下處理:

sortingalgorithms.heapsort(&myarray)

複製**

而是這樣:

myarray.heapsort()

複製**

這樣更加清晰。元素型別不符合 comparable 協議時,編輯器甚至不會在陣列物件上智慧型提示 .heapsort()。

public

extension

array

where

element: comparable

private

mutating

func

buildheap()

}}

private

mutating

func

shrinkheap

() else

if rightchild < index && self[rightchild] > self[maxchild]

guard

self[maxchild] > self[parent] else

swapat(parent, maxchild)

parent = maxchild

leftchild = parent.leftchild

rightchild = parent.rightchild}}

}}複製**

done!!!

堆排序(Swift版本)

一 什麼是堆?堆可視為 以陣列方式儲存的一棵完全二叉樹 堆又分為最大堆和最小堆,最大堆就是對於整個二叉樹中的每乙個節點都滿足 節點的鍵值比其左右子節點的鍵值都要大,對應的最小堆則是 節點的鍵值比其左右子節點的鍵值都要小 二 堆排序的思路 對於乙個儲存最大堆的陣列arr 長度為size 根節點arr ...

堆排序實現

今天抽空寫了個堆排序的演算法,廢話不多說,直接上源 include include includeusing namespace std define maxsize 6 void print int a,int size maxsize void percolate up int a,int si...

堆排序實現

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