源自國內開發者喜愛的泊學網
插入排序是最基礎的排序演算法之一。它最核心的思想,由以下幾條構成。當我們要對乙個值為[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
&insert
或swap
之外,還有一種插入排序的手段。用之前的[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 省略下標 能夠匹...