通過演算法了解Swift 3 插入排序

2021-07-23 13:52:34 字數 3380 閱讀 1032

源自國內開發者喜愛的泊學網

插入排序是最基礎的排序演算法之一。它最核心的思想,由以下幾條構成。當我們要對乙個值為[1, 5, 6]

的陣列從大到小排列時:

1.把序列的第乙個元素想象成乙個「子串行」[1],它是已經排序的;

2.按照既定的排序規則,把由序列的前兩個元素構成的「子串行」排序:[5, 1]

3.之後,讀入6,在之前已經排序好的「子串行」中,從右向左逐個和新讀入的元素進行比對。如果滿足排序規則,就交換已排序陣列中的元素和待排序的元素:

[5, 1, 6] 

^ 6 > 1 == true

[5, 1, 6]

swap

[5, 6, 1]

簡單來說,就是不斷通過比對,移動待排序元素的位置。直到待排序元素和之前已排序「子串行」全部元素都比對完之後:

[5, 6, 1] 

^ 6 > 5 == true

[5, 6, 1]

swap

[6, 5, 1]

新形成的序列就已經是排序好的了。(當然,這裡也有乙個潛台詞,就是如果和子串行中第乙個元素比對之後不需要移動,則新新增進來的元素就應該直接新增到子串行末尾);

- 反覆3的操作,當讀完所有待排序的元素之後,整個序列就排序完成了;

在理解插入排序的時候,要時刻記住一件事情:元素的操作永遠只發生在相鄰的兩個元素之間。當我們在頭腦中執行插入排序時,偶爾會忘記這條,會想著是否存在著跨元素交換的情況,然後就把自己搞暈了。

在實現之前,我們要先考慮下開發者會如何使用這個演算法,例如這樣:

let a: array

= [1, 5, 6]

insertionsortof(a)

或者,我們允許使用者指定乙個排序方法

let a: array

= [1, 5, 6]

insertionsortof(a, bycriteria: >) // [6, 5, 1]

然後,我們還應該允許對包含任何「可比較」元素的array進行排序。於是,insertionsort的宣告可以是下面這樣的。

typealias criteria = (t, t) -> bool

func insertionsortof(

_ coll: array,

bycriteria: criteria = ) ->array

中使用泛型引數**;

其次,在方法的命名上,我們參考了se-0023 api設計指南中的要求:

「如果方法中第乙個引數和方法名一起形成了乙個語法正確的短語,去掉第乙個引數的label,並且把引數label放到方法名中」

; -要為方法中的closure引數設定label:因此,我們沒有去掉第二個closure引數的label;

-當方法的引數在絕大多數時候使用相同值時,應為它指定預設值:因此,我們讓bycriteria

的預設行為是按公升序排列;

按照一開始我們在演算法思路中的描述,在insertionsort

中新增下面的**:

首先,只有乙個元素的陣列是無需排序的,我們直接返回就好:

func insertionsortof( 

_ coll: array,

bycriteria: criteria = ) -> array

}

其次,複製乙份引數陣列,用於在函式內部進行排序:

func insertionsortof(

_ coll: array,

bycriteria: criteria = ) -> array

var result = coll

}

第三,我們從陣列中第二個元素開始,通過逐個比對,來不斷形成已排序好的子陣列:

for x in

1 ..< coll.count

}

最後,陣列中所有的元素都遍歷之後,整個陣列就完成排序了,我們直接把排序後的陣列返回:

func insertionsortof(

_ coll: array

, bycriteria: criteria= ) -> array

var result = coll

for x in 1 ..< coll.count

} // 4. return the sorted array

return result

}

用一開始我們設計的使用方法來測試insertionsort

let a: array

= [1, 5, 6]

insertionsortof(a)

由於預設就是從小到大排序,並且,原始陣列本身就是已經排序的,因此,我們可以在控制台看到下面的結果:

如果我們傳遞乙個自定義的比較規則,例如從大到小排序:

let a: array

= [1, 5, 6]

insertionsortof(a, bycriteria: >)

就可以在控制台看到這樣的結果:

數字5經歷了一次交換,數字6經歷了兩次交換。

除了使用remove&insertswap

之外,還有一種插入排序的手段。用之前的[1, 5, 6]

降序排枚舉例。假設演算法執行到了讀入數字6:

1.記錄讀入的值:

[5,

1,6]

^--> remember

6

2.在新讀入位置前已排序好的子陣列裡,不斷用前乙個數字覆蓋後乙個位置,為新讀入的元素找到合適的位置:

[5, 1, 1]

--> shift 1 right

[5, 5, 1]

--> shift 5 right

[6, 5, 1]

^ --> copy 6 here

Swift3建立陣列

陣列是由一組型別相同的元素構成的有序資料集合。陣列中的集合元素是有 序的,而且可以重複出現。在swift語言中,陣列的型別格式為 array或 elementtype 其中array中的elementtype表示陣列的型別,是泛型寫法。elementtype 是一種簡寫方式。兩者表示的功能是一樣的,...

Swift3 建立字典

字典是由兩部分內容構成的,乙個是鍵 key 乙個是值 value 字典是一種儲存多個型別相同的值的容器。每個值都和乙個唯一的鍵相對應,這個鍵在字典裡就是其對應值的唯一標識。鍵是不能有重複元素的,而值是可以重複的 鍵和值是成對出現的。跟陣列不同,字典裡的元素並沒有特定的順序。在 字典 中使用鍵來查詢其...

從零學習Swift 3

oc 風格的迴圈var sum 0 for var i 0 i 10 i print sum for in,0.10 表示從0到9 sum 0 for i in 0.10 print sum 範圍 0.10 表示從0到10 sum 0 for i in 0.10 print sum 省略下標 能夠匹...