Swift數(shù)據(jù)結(jié)構(gòu)和算法02_Swift標(biāo)準(zhǔn)庫(kù)

前言

有需要的同學(xué)可以訂閱專(zhuān)欄:Swift數(shù)據(jù)結(jié)構(gòu)和算法專(zhuān)題
代碼地址:Swift數(shù)據(jù)結(jié)構(gòu)和算法代碼

正文

在本章中,我們將關(guān)注標(biāo)準(zhǔn)庫(kù)開(kāi)箱即用的三個(gè)主要數(shù)據(jù)結(jié)構(gòu):數(shù)組、字典和集合持搜。

數(shù)組

數(shù)組是一種通用的通用容器,用于存儲(chǔ)有序的元素集合劫樟,它在各種 Swift 程序中普遍使用。我們可以使用數(shù)組字面量創(chuàng)建數(shù)組织堂,數(shù)組字面量是由方括號(hào)括起來(lái)的以逗號(hào)分隔的值列表叠艳。例如:

let people = ["Brian", "Stanley", "Ringo"]

Swift 使用協(xié)議定義數(shù)組。這些協(xié)議中的每一個(gè)都在陣列上分層了更多功能易阳。例如附较,一個(gè)數(shù)組是一個(gè)序列,這意味著我們可以至少迭代一次潦俺。它也是一個(gè)集合拒课,這意味著它可以被多次非破壞性地遍歷,并且可以使用下標(biāo)運(yùn)算符進(jìn)行訪問(wèn)事示。數(shù)組也是一個(gè)RandomAccessCollection早像,它保證了效率很魂。

Swift Array 被稱為泛型集合扎酷,因?yàn)樗梢蕴幚砣魏晤?lèi)型遏匆。事實(shí)上,大部分 Swift 標(biāo)準(zhǔn)庫(kù)都是用通用代碼構(gòu)建的幅聘。與任何數(shù)據(jù)結(jié)構(gòu)一樣,我們應(yīng)該注意某些值得注意的特征帝蒿。首先 其中包括秩序的概念荐糜。數(shù)組中的元素是明確排序的葛超。以上述人員數(shù)組為例,“Brian”排在“Stanley”之前绣张。數(shù)組中的所有元素都有一個(gè)對(duì)應(yīng)的從零開(kāi)始的整數(shù)索引。例如侥涵,上面示例中的 people 數(shù)組具有三個(gè)索引,一個(gè)對(duì)應(yīng)于每個(gè)元素芜飘。我們可以通過(guò)編寫(xiě)以下代碼來(lái)檢索數(shù)組中元素的值:

people[0] // "Brian" 
people[1] // "Stanley" 
people[2] // "Ringo" 
復(fù)制代碼

順序由數(shù)組數(shù)據(jù)定義結(jié)構(gòu),不應(yīng)被視為理所當(dāng)然嗦明。某些數(shù)據(jù)結(jié)構(gòu),例如 Dictionary娶牌,具有較弱的順序概念。

隨機(jī)訪問(wèn)

如果數(shù)據(jù)結(jié)構(gòu)可以在恒定時(shí)間內(nèi)處理元素檢索裙戏,則隨機(jī)訪問(wèn)是一種特征。例如累榜,從 people 數(shù)組中獲取“Ringo”需要恒定的時(shí)間。同樣壹罚,這種表現(xiàn)不應(yīng)被視為理所當(dāng)然。其他數(shù)據(jù)結(jié)構(gòu)猖凛,如鏈表和樹(shù),沒(méi)有固定時(shí)間訪問(wèn)辨泳。

數(shù)組性能

除了作為隨機(jī)訪問(wèn)集合之外玖院,作為開(kāi)發(fā)人員第岖,我們還對(duì)其他性能領(lǐng)域感興趣难菌,特別是當(dāng)數(shù)據(jù)結(jié)構(gòu)包含的數(shù)據(jù)量需要增長(zhǎng)時(shí)蔑滓,它的表現(xiàn)如何?對(duì)于數(shù)組键袱,這取決于兩個(gè)因素。

插入位置

第一個(gè)因素是我們選擇在數(shù)組中插入新元素的因素蹄咖。將元素添加到數(shù)組的最有效方案是將其附加到數(shù)組的末尾:

people.append("Charles") 
print(people) // prints ["Brian", "Stanley", "Ringo", "Charles"]
復(fù)制代碼

使用 append 方法插入 "Charles" 會(huì)將字符串放在數(shù)組的末尾。這是一個(gè)恒定時(shí)間操作比藻,這意味著無(wú)論數(shù)組有多大,執(zhí)行此操作所需的時(shí)間都保持不變银亲。但是,有時(shí)我們可能需要在特定位置插入元素务蝠,例如在數(shù)組的最中間。

為了幫助說(shuō)明為什么會(huì)出現(xiàn)這種情況馏段,請(qǐng)考慮以下類(lèi)比。你正在排隊(duì)等劇院院喜。新來(lái)的人加入了陣容。將人員添加到陣容中最容易的地方是什么喷舀?最后,當(dāng)然硫麻!

如果新人試圖將自己插入隊(duì)伍的中間,他將不得不說(shuō)服一半的陣容重新洗牌以騰出空間拿愧。

如果他非常粗魯,他會(huì)試圖把自己插在隊(duì)伍的最前面。這是最壞的情況券敌,因?yàn)殛嚾葜械拿總€(gè)人都需要重新洗牌,為前面的新人騰出空間陪白!

這正是數(shù)組的工作原理膳灶。從數(shù)組末尾以外的任何地方插入新元素將強(qiáng)制元素向后移動(dòng)以為新元素騰出空間:

people.insert("Andy", at: 0) 
// ["Andy", "Brian", " Stanley", "Ringo", "Charles"] 
復(fù)制代碼

準(zhǔn)確地說(shuō),每個(gè)元素必須向后移動(dòng)一個(gè)索引轧钓,這需要 n 步。如果數(shù)組中的元素?cái)?shù)量加倍毕箍,則此插入操作所需的時(shí)間也將加倍。

如果在集合前面插入元素是程序的常見(jiàn)操作而柑,我們可能需要考慮使用不同的數(shù)據(jù)結(jié)構(gòu)來(lái)保存數(shù)據(jù)。

決定插入速度的第二個(gè)因素是陣列的容量媒咳。在底層,Swift 數(shù)組為其元素分配了預(yù)定數(shù)量的空間涩澡。如果我們嘗試將新元素添加到已達(dá)到最大容量的數(shù)組中,則該數(shù)組必須自行重組妙同,以便為更多元素騰出更多空間。這是通過(guò)復(fù)制所有當(dāng)前元素來(lái)完成的 在內(nèi)存中一個(gè)新的更大的容器中的數(shù)組粥帚。然而,這是有代價(jià)的芒涡;必須訪問(wèn)和復(fù)制數(shù)組的每個(gè)元素。這意味著如果進(jìn)行了復(fù)制拖陆,任何插入,即使是在最后依啰,也可能需要 n 步才能完成。但是,標(biāo)準(zhǔn)庫(kù)采用了一種策略叹誉,可以最大限度地減少這種復(fù)制需要發(fā)生的時(shí)間。每次它用完存儲(chǔ)空間并需要復(fù)制時(shí)长豁,它的容量就會(huì)增加一倍。

字典

字典是另一個(gè)保存鍵值對(duì)的通用集合匠襟。例如,這是一個(gè)包含用戶名和分?jǐn)?shù)的字典:

var score: [String: Int] = ["Eric": 9, "Mark": 12, "Wayne": 1]
復(fù)制代碼

字典沒(méi)有任何順序保證酸舍,也不能在特定索引處插入。他們還對(duì) Key 類(lèi)型提出了要求啃勉,即它是 Hashable。幸運(yùn)的是淮阐,幾乎所有的標(biāo)準(zhǔn)類(lèi)型都已經(jīng)是 Hashable 并且在 Swift 的最新版本中,采用 Hashable 協(xié)議現(xiàn)在是微不足道的泣特。我們可以使用以下語(yǔ)法向字典中添加新條目:

scores["Andrew"] = 0
復(fù)制代碼

這將在字典中創(chuàng)建一個(gè)新的鍵值對(duì):

["Eric": 9, "Mark": 12, "Andrew": 0, "Wayne": 1] 
復(fù)制代碼

"Andrew" 鍵被插入到字典的某個(gè)位置。字典是無(wú)序的群扶,所以你不能保證新條目會(huì)放在哪里。

正如 Collection 協(xié)議所提供的竞阐,可以多次遍歷字典的鍵值。這個(gè)順序雖然沒(méi)有定義骆莹,但每次遍歷時(shí)都是相同的,直到集合發(fā)生變化(突變)幕垦。

缺乏明確的排序劣勢(shì)帶來(lái)了一些可取之處。

與數(shù)組不同先改,字典不需要擔(dān)心元素的移動(dòng)。插入字典總是需要一定的時(shí)間仇奶。查找操作也需要一定的時(shí)間,這比在數(shù)組中查找需要從數(shù)組開(kāi)頭到插入點(diǎn)的特定元素要快得多。

集合

集合是一個(gè)包含唯一值的容器别惦。想象它是一個(gè)包 允許我們將項(xiàng)目插入其中,但拒絕已插入的項(xiàng)目:

var bag: Set<String> = ["Candy", "Juice", "Gummy"] 
bag.insert("Candy") 
print(bag) // prints ["Candy", "Juice", "Gummy"] 
復(fù)制代碼

由于集合強(qiáng)制唯一性掸掸,它們適用于各種有趣的應(yīng)用,例如在值集合中查找重復(fù)元素:

let values: [String] = [ ...] 
var bag: Set<String> = [] 
for value in values { 
  if bag.contains(value) { 
    // bag 已經(jīng)有了它扰付,因此它是重復(fù)的 
  } 
  bag.insert(value) 
} 
復(fù)制代碼

使用集合的次數(shù)幾乎不會(huì)與與數(shù)組和字典一樣多,但它仍然很常見(jiàn)悯周,可以作為重要的數(shù)據(jù)結(jié)構(gòu)保存在我們的工具帶中。不過(guò),有一個(gè)警告屠橄。與字典類(lèi)似,集合中的值沒(méi)有順序的概念锐墙。當(dāng)我們使用集合來(lái)聚合數(shù)據(jù)時(shí),請(qǐng)記住這一點(diǎn)溪北。

Swift Collections 包

Swift 標(biāo)準(zhǔn)庫(kù)只實(shí)現(xiàn)了三個(gè)最重要的數(shù)據(jù)結(jié)構(gòu):ArraySetDictionary之拨。對(duì)于其他數(shù)據(jù)結(jié)構(gòu),我們可以查看 Swift Collections 包蚀乔。這個(gè)包允許社區(qū)在它們成為官方標(biāo)準(zhǔn)庫(kù)的一部分之前開(kāi)發(fā)和測(cè)試新的集合類(lèi)型。

在下一節(jié)中吉挣,我們將更深入地了解此包中的一個(gè)數(shù)據(jù)結(jié)構(gòu)。

Deque

之前睬魂,我們了解到在 Array 的前面插入元素會(huì)導(dǎo)致所有元素的混洗。乍一看氯哮,Deque(讀作“deck”)數(shù)據(jù)結(jié)構(gòu)似乎與 Array 具有相同的用途。我們可以將其用作按順序保存值的通用容器。就像數(shù)組一樣垫卤,我們可以調(diào)用 append 將元素添加到 Deque,或調(diào)用 remote(at:) 以刪除某個(gè)索引處的特定元素穴肘。事實(shí)上,接口幾乎是相同的评抚,因?yàn)?ArrayDeque 都實(shí)現(xiàn)了相同的收集協(xié)議。 那么為什么要在數(shù)組上使用雙端隊(duì)列呢慨代?除非我們考慮時(shí)間復(fù)雜度,否則很難看到權(quán)衡取舍侍匙。 Deque 是一個(gè)雙端隊(duì)列。因此想暗,Deque 針對(duì)集合前后的修改進(jìn)行了優(yōu)化。與 Array 不同说莫,從 Deque 的前面插入或刪除元素是一種快速的 O(1) 操作。太好了 - 那么有什么缺點(diǎn)呢储狭?在編程中,一切都是關(guān)于權(quán)衡的辽狈。對(duì)于 Deque,它是關(guān)于改進(jìn)前端的修改稻艰,以犧牲其他所有方面的性能略有下降。作為程序員尊勿,我們的工作是權(quán)衡選項(xiàng)并選擇最適合工作的工具。如果我們的應(yīng)用程序需要頻繁修改集合的前面元扔,則 Deque 的性能將比 Array 好得多。這可以轉(zhuǎn)化為更好的用戶體驗(yàn)——一種可以在快速和緩慢的應(yīng)用程序之間產(chǎn)生差異的體驗(yàn)澎语。 Swift Collections 包包含額外的數(shù)據(jù)結(jié)構(gòu)验懊,例如 OrderedDictionaryOrderedSet。正如前綴所暗示的义图, 這些是 DictionarySet 的變體,它們保留了元素的順序碱工。與 Deque 一樣,這些數(shù)據(jù)結(jié)構(gòu)也有一些性能折衷怕篷。我們可以在 swift.org/blog/swift-… 了解更多關(guān)于它們的信息。

關(guān)鍵點(diǎn)

? 每個(gè)數(shù)據(jù)結(jié)構(gòu)都有優(yōu)點(diǎn)和缺點(diǎn)酗昼。了解它們是編寫(xiě)高性能軟件的關(guān)鍵廊谓。

? 用于Arrayinsert(at:) 等函數(shù)具有性能特征麻削,在隨意使用時(shí)會(huì)削弱性能蒸痹。如果我們發(fā)現(xiàn)自己需要經(jīng)常在數(shù)組開(kāi)頭附近使用帶有索引的 insert(at:)碟婆,我們可能需要考慮使用不同的數(shù)據(jù)結(jié)構(gòu),例如鏈表竖共。

? 字典放棄了保持其元素順序的能力俺祠,以實(shí)現(xiàn)快速插入和搜索公给。

? Set 保證值集合的唯一性蜘渣。Set針對(duì)速度進(jìn)行了優(yōu)化,放棄了保留元素順序的能力蔫缸。

? Swift Collections 包包含在某些場(chǎng)景中表現(xiàn)更好的專(zhuān)用數(shù)據(jù)結(jié)構(gòu)。

上一章 目錄 下一章
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拾碌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子校翔,更是在濱河造成了極大的恐慌,老刑警劉巖防症,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哎甲,死亡現(xiàn)場(chǎng)離奇詭異饲嗽,居然都是意外死亡炭玫,警方通過(guò)查閱死者的電腦和手機(jī)貌虾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)酝惧,“玉大人,你說(shuō)我怎么就攤上這事晚唇。” “怎么了哩陕?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)悍及。 經(jīng)常有香客問(wèn)我,道長(zhǎng)心赶,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任缨叫,我火速辦了婚禮,結(jié)果婚禮上耻姥,老公的妹妹穿的比我還像新娘。我一直安慰自己琐簇,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布婉商。 她就那樣靜靜地躺著,像睡著了一般据某。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上癣籽,一...
    開(kāi)封第一講書(shū)人閱讀 48,954評(píng)論 1 283
  • 那天滤祖,我揣著相機(jī)與錄音,去河邊找鬼匠童。 笑死,一個(gè)胖子當(dāng)著我的面吹牛汤求,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播严拒,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼挤牛!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起种蘸,我...
    開(kāi)封第一講書(shū)人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诫硕,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體章办,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年纲菌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疮绷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡冬骚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出懂算,到底是詐尸還是另有隱情,我是刑警寧澤计技,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站垮媒,受9級(jí)特大地震影響航棱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜饮醇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一秕豫、第九天 我趴在偏房一處隱蔽的房頂上張望朴艰。 院中可真熱鬧混移,春花似錦祠墅、人聲如沸歌径。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至勺届,卻和暖如春驶俊,著一層夾襖步出監(jiān)牢的瞬間免姿,已是汗流浹背饼酿。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工胚膊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人紊婉。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像喻犁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肢础,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容