【譯】Swift算法俱樂(lè)部-計(jì)數(shù)排序

Swift算法俱樂(lè)部

本文是對(duì) Swift Algorithm Club 翻譯的一篇文章伪朽。
Swift Algorithm Clubraywenderlich.com網(wǎng)站出品的用Swift實(shí)現(xiàn)算法和數(shù)據(jù)結(jié)構(gòu)的開(kāi)源項(xiàng)目导犹,目前在GitHub上有18000+??湖苞,我初略統(tǒng)計(jì)了一下彬檀,大概有一百左右個(gè)的算法和數(shù)據(jù)結(jié)構(gòu),基本上常見(jiàn)的都包含了,是iOSer學(xué)習(xí)算法和數(shù)據(jù)結(jié)構(gòu)不錯(cuò)的資源。
??andyRon/swift-algorithm-club-cn是我對(duì)Swift Algorithm Club摇庙,邊學(xué)習(xí)邊翻譯的項(xiàng)目。由于能力有限遥缕,如發(fā)現(xiàn)錯(cuò)誤或翻譯不妥卫袒,請(qǐng)指正,歡迎pull request单匣。也歡迎有興趣夕凝、有時(shí)間的小伙伴一起參與翻譯和學(xué)習(xí)??烤蜕。當(dāng)然也歡迎加??,??????????迹冤。
本文的翻譯原文和代碼可以查看??swift-algorithm-club-cn/Counting Sort


計(jì)數(shù)排序(Counting Sort)

Counting sort is an algorithm for sorting a collection of objects according to keys that are small integers. It operates by counting the number of objects that have each distinct key values, and using arithmetic on those counts to determine the positions of each key value in the output sequence.
計(jì)數(shù)排序是一種根據(jù)小整數(shù)鍵對(duì)對(duì)象集合進(jìn)行排序的算法。通過(guò)計(jì)算具有每個(gè)不同鍵值的對(duì)象的數(shù)量來(lái)操作虎忌,并對(duì)這些計(jì)數(shù)使用算術(shù)來(lái)確定輸出序列中每個(gè)鍵值的位置泡徙。

例子

為了理解算法,讓我們來(lái)看一個(gè)小例子膜蠢。

考慮數(shù)組: [ 10, 9, 8, 7, 1, 2, 7, 3 ]

第一步:

第一步是計(jì)算數(shù)組中每個(gè)項(xiàng)的總出現(xiàn)次數(shù)堪藐。 第一步的輸出將是一個(gè)新的數(shù)組,如下所示:

Index 0 1 2 3 4 5 6 7 8 9 10
Count 0 1 1 1 0 0 0 2 1 1 1

譯注: 這邊Index的最大值對(duì)應(yīng)于挑围,數(shù)組中最大值10礁竞。

這是完成第一步的代碼:

  let maxElement = array.max() ?? 0

  var countArray = [Int](repeating: 0, count: Int(maxElement + 1))
  for element in array {
    countArray[element] += 1
  }

第二步:

在此步驟中,算法嘗試確定在每個(gè)元素之前放置的元素的數(shù)量杉辙。通過(guò)第一步已經(jīng)知道每個(gè)元素的總出現(xiàn)次數(shù)模捂,可以得到。方法就是把前一個(gè)計(jì)數(shù)和當(dāng)前計(jì)數(shù)相加存儲(chǔ)到每個(gè)索引中(對(duì)應(yīng)代碼就是countArray[index] + countArray[index - 1])蜘矢。

計(jì)數(shù)數(shù)組如下:

Index 0 1 2 3 4 5 6 7 8 9 10
Count 0 1 2 3 3 3 3 5 6 7 8

第二步的代碼:

  for index in 1 ..< countArray.count {
    let sum = countArray[index] + countArray[index - 1]
    countArray[index] = sum
  }

第三步

這是算法的最后一步狂男。 原始數(shù)組中的每個(gè)元素都放置在第二步的輸出定義的位置。例如品腹,數(shù)字10將放在輸出數(shù)組中的索引7處岖食。 此外,當(dāng)您放置元素時(shí)舞吭,您需要將計(jì)數(shù)減少1泡垃,因?yàn)閺臄?shù)組中減少了許多元素。

最終的輸出是:

Index  0 1 2 3 4 5 6 7
Output 1 2 3 7 7 8 9 10

以下是最后一步的代碼:

  var sortedArray = [Int](repeating: 0, count: array.count)
  for element in array {
    countArray[element] -= 1
    sortedArray[countArray[element]] = element
  }
  return sortedArray

性能

該算法使用簡(jiǎn)單循環(huán)對(duì)集合進(jìn)行排序羡鸥。 因此蔑穴,運(yùn)行整個(gè)算法的時(shí)間是O(n+k)其中O(n)表示初始化輸出數(shù)組所需的循環(huán),O(k)是創(chuàng)建計(jì)數(shù)數(shù)組所需的循環(huán)兄春。

該算法使用長(zhǎng)度為n + 1n的數(shù)組澎剥,因此所需的總空間為O(2n)。 因此赶舆,對(duì)于密鑰沿著數(shù)字線分散在密集區(qū)域中的集合哑姚,它可以節(jié)省空間。

作者:Ali Hafizji
翻譯:Andy Ron
校對(duì):Andy Ron


翻譯后補(bǔ)充

計(jì)數(shù)排序假設(shè)n個(gè)輸入元素中的每一個(gè)都是在0到k區(qū)間內(nèi)的一個(gè)整數(shù)芜茵,其中k為某個(gè)整數(shù)叙量。當(dāng)k=O(n)時(shí),排序的運(yùn)行時(shí)間為Θ(n)九串。

計(jì)數(shù)排序的思想是绞佩,對(duì)每一個(gè)輸入元素寺鸥,計(jì)算小于它的元素個(gè)數(shù),如果有10個(gè)元素小于它品山,那么它就應(yīng)該放在11的位置上胆建,如果有17個(gè)元素小于它,它就應(yīng)該放在18的位置上肘交。當(dāng)有幾個(gè)元素相同時(shí)笆载,這一方案要略做修改,因?yàn)椴荒馨阉鼈兎旁谕粋€(gè)輸出位置上涯呻。下圖(來(lái)源于《算法導(dǎo)論》)展示了實(shí)際的運(yùn)行過(guò)程凉驻。

基數(shù)排序(來(lái)源于《算法導(dǎo)論》)

構(gòu)造輔助數(shù)組C,C的長(zhǎng)度為k复罐。第一次遍歷A后涝登,得到[0,k)區(qū)間上每個(gè)數(shù)出現(xiàn)的次數(shù),將這些次數(shù)寫入C效诅,得到圖(a)的結(jié)果胀滚。然后把C中每個(gè)元素變成前面所有元素的累加和,得到圖(b)的結(jié)果填帽。接下來(lái)蛛淋,再次從后向前遍歷數(shù)組A,根據(jù)取出的元素查找C中對(duì)應(yīng)下標(biāo)的值篡腌,再把這個(gè)值作為下標(biāo)找到B中的位置褐荷,即是該元素排序后的位置。例如嘹悼,圖中A的最后一個(gè)元素是3叛甫,找到C[3]是7,再令B[7]=3即可杨伙,然后順便把C[3]減一其监,這是防止相同的數(shù)被放到同一個(gè)位置。

計(jì)數(shù)排序的時(shí)間代價(jià)可以這樣計(jì)算限匣,第一次遍歷A并計(jì)算C所花時(shí)間是Θ(n)抖苦,C累加所花時(shí)間是Θ(k),再次遍歷A并給B賦值所花時(shí)間是Θ(n)米死,因此锌历,總時(shí)間為Θ(k + n)。在實(shí)際中峦筒,當(dāng)k=O(n)時(shí)究西,我們一般會(huì)采用計(jì)數(shù)排序,這時(shí)的運(yùn)行時(shí)間為Θ(n)物喷。

參考

http://www.reibang.com/p/ff1797625d66

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末卤材,一起剝皮案震驚了整個(gè)濱河市遮斥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扇丛,老刑警劉巖术吗,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異帆精,居然都是意外死亡藐翎,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門实幕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人堤器,你說(shuō)我怎么就攤上這事昆庇。” “怎么了闸溃?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵整吆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我辉川,道長(zhǎng)表蝙,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任乓旗,我火速辦了婚禮府蛇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘屿愚。我一直安慰自己汇跨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布妆距。 她就那樣靜靜地躺著穷遂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪娱据。 梳的紋絲不亂的頭發(fā)上蚪黑,一...
    開(kāi)封第一講書(shū)人閱讀 51,488評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音中剩,去河邊找鬼忌穿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛咽安,可吹牛的內(nèi)容都是我干的伴网。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼妆棒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼澡腾!你這毒婦竟也來(lái)了沸伏?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤动分,失蹤者是張志新(化名)和其女友劉穎毅糟,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體澜公,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姆另,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了坟乾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迹辐。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖甚侣,靈堂內(nèi)的尸體忽然破棺而出明吩,到底是詐尸還是另有隱情,我是刑警寧澤殷费,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布印荔,位于F島的核電站,受9級(jí)特大地震影響详羡,放射性物質(zhì)發(fā)生泄漏仍律。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一实柠、第九天 我趴在偏房一處隱蔽的房頂上張望水泉。 院中可真熱鬧,春花似錦窒盐、人聲如沸茶行。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)畔师。三九已至,卻和暖如春牧牢,著一層夾襖步出監(jiān)牢的瞬間看锉,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工塔鳍, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留伯铣,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓轮纫,卻偏偏與公主長(zhǎng)得像腔寡,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掌唾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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