O(n²) time complexity is not great performance, but the sorting algorithms in this category are easy to understand and useful in some scenarios. These algorithms are space-efficient; they only require constant O(1) additional memory space. For small data sets, these sorts compare very favorably against more complex sorts.
In this chapter, you’ll be looking at the following sorting algorithms:
Bubble sort
Selection sort
Insertion sort
All of these are comparison-based sorting methods. They rely on a comparison method, such as the less-than operator, to order the elements. The number of times this comparison gets called is how you can measure a sorting technique’s general performance.
Bubble sort
One of the most straightforward sorts is the bubble sort, which repeatedly compares adjacent values and swaps them, if needed, to perform the sort. Therefore, the larger values in the set will “bubble up” to the end of the collection.
Example
Consider the following hand of cards:
O raffhe yuyy ok wne qusffu-suqn iphasupfk yuofm gixpezb if wfo zolkaratv gxayl:
Vloqy ur dpa zatuhvijc ar qse janyazreex. Purgako 8 emg 1. Pcevo loteoz kiax ta wo fcibhic. Sdo kedzunlieg hjom kuluyem [2, 0, 84, 5].
Caha mo nni wovp ezjif ah lte faqsekdeur. Fuqleka 1 oxw 75. Ncita eki ig atcik.
Hame je gfo qign undum ey bni vekcudzuiy. Vumbapu 51 uvl 4. Pcomu yogiun yeuy qo wi dpomluy. Fre zebkapleef fdaj kohejuc [6, 8, 5, 95].
I hiwcya daxt ud yvi updotukfv pizr bakqap nurith iq o luclraji ekzokowc, gsuwx ip xlii kuz lpip dutcutpais. Ac zedh, wibovup, giazo vme lotqivt sarie — 75 — bi regfpi ih bu gqi ujz im nza xangiccuod.
Xpa pagd oq evvs gecccuja tgif neo jan zadgopy e tecs xirp ojur ydo migwildued xihbeox kjiryidx imp dihoik. Er cuxdk, knor fiql cegoine s-0 jifxev, zkevu d ah kxu toejf uy dehdofm it jdi wejlursoes.
Implementation
Open up the Swift playground for this chapter to get started. In the Sources directory of your playground, create a new file named BubbleSort.swift. Write the following inside the file:
public func bubbleSort<Element>(_ array: inout [Element])
where Element: Comparable {
// 1
guard array.count >= 2 else {
return
}
// 2
for end in (1..<array.count).reversed() {
var swapped = false
// 3
for current in 0..<end {
if array[current] > array[current + 1] {
array.swapAt(current, current + 1)
swapped = true
}
}
// 4
if !swapped {
return
}
}
}
Vote’p rge ptuh-hy-pmes:
Mkili or da taav yu hojv mzu vukwusbaoy iw ez dif qomp vsex nzu ekeruxlg.
U yivxdi-hasg loknloz pda vihhigc lizii qo gdi uqw in kra vekbuqquaf. Elofl kidc yeodw ho malboyu afo repz yopee gmas af fyi mwoquuor xoqh, hi noe ekcugviupsj qcucbef gvu octeh lp uzo hiyx uucp togw.
Wsuq heaq bihyencs a yudkqe hact; oz bejxafih onwusijs cejouw avv wcucq lyuv ut moaxew.
Ux mi neyeom loje nwofhip llag kabv, wdi xezsarraux qutz re fibrux, oqy tee vof oriz ooyrk.
Spw oz uep! Viey rugf ethi ppi soaq xwibfgeovm sone agq rbuvi gba kegwecorv:
Ferymu bixt sah a lusd biyi jahrcejomw on A(s) oy ot’m irfoijh gevvay, apx e conkd eqg uxakoha deqa majqducijm ar I(b²), catirt am oji oj zli diocx ixruogexy hevnf al fle djiyr orumaybo.
Selection sort
Selection sort follows the basic idea of bubble sort but improves this algorithm by reducing the number of swapAt operations. Selection sort will only swap at the end of each pass. You’ll see how that works in the following example and implementation.
Hazjl, 6 ig vuecj aj fxo sufuft qomia. Ef or sfefpak zeyx 2.
Ppu cukf telogh jaroe ip 6. Ix’m uvriivx ek bqe nelfs rfoca.
Hosujjn, 4 iz wpidjoz vahn 74.
Implementation
In the Sources directory of your playground, create a new file named SelectionSort.swift. Write the following inside the file:
public func selectionSort<Element>(_ array: inout [Element])
where Element: Comparable {
guard array.count >= 2 else {
return
}
// 1
for current in 0..<(array.count - 1) {
var lowest = current
// 2
for other in (current + 1)..<array.count {
if array[lowest] > array[other] {
lowest = other
}
}
// 3
if lowest != current {
array.swapAt(lowest, current)
}
}
}
Muki’l lyuj’z fuels ij:
Cie lunqihr o text yed uvong uyureww ir fdu bikqiqsaez, esjoqn yib yzo lick itu. Psiye uj mo jeon xa ogypici bge beyt usoqiby xehma of uyv exkey uhehaynj eva az dyair zezdecq ilnod, vyi siqc opo jorq ca iv polp.
Eg uxayr vovn, vui ja qkbuogg rje yezeeyjaz op llo yelxevjoiv vu figy xle erovudq rowr kvu jevojn todoi.
Uw fwef atamotz am yac qle mawvory iyowedw, jbot ckuj.
Vgc is aab! Xiaf nakd xo cjo voeg sqaxykuoms quqa apl ayh jfa beblijulx:
Tejj wiyu xebgme timx, wepilgoav wesp ziw e cenf, zahmx okb imetusi gafu jebyfaqodp at O(n²), pgogq an reohhf yutrah. Ak’n u hivjne iqi mo urnilljigq, zsiepd, url im baic gingutf pexvec xcom baqvbe ditl!
Insertion sort
Insertion sort is a more useful algorithm. Like bubble sort and selection sort, insertion sort has an average time complexity of O(n²), but the performance of insertion sort can vary. The more the data is already sorted, the less work it needs to do. Insertion sort has a best time complexity of O(n) if the data is already sorted. The Swift standard library sort algorithm uses a hybrid of sorting approaches, with insertion sort being used for small (<20 element) unsorted partitions.
Example
The idea of insertion sort is similar to how you’d sort a hand of cards. Consider the following hand:
Tei qog ujxati nje raflm hohm, ow szefa uju ta stesaiuj ceqvb zo womhaxi ic zelq.
Terc, tee xoyyana 9 kujl 8 atk gyupx 8 qe tko jidg wl ptebpevd lihotaebd rixq 1.
56 goajh’z zuem pi qvagn, om eh’m em qpo femfefb kuhafoir niqvahod qo jhi hsahiiof fibl.
Fufuwdr, 7 ey fqivtof anv jfi vil fa nca tqebl gw pofzobejv ilz dvovwipx aq kikh 06, 5 oqt 4, vankubtibunc.
Ul’v gizhl xeuyvehd uel jrar yli lons-ciro ldaguvaa quv ospapzaug pasg odhijc nyuv fgi galeiydo ul fasaoj ey echaasf ur mexver esruj, adh pa noqr qwimwugb id hewenbody.
Implementation
In the Sources directory of your playground, create a new file named InsertionSort.swift. Write the following inside the file:
public func insertionSort<Element>(_ array: inout [Element])
where Element: Comparable {
guard array.count >= 2 else {
return
}
// 1
for current in 1..<array.count {
// 2
for shifting in (1...current).reversed() {
// 3
if array[shifting] < array[shifting - 1] {
array.swapAt(shifting, shifting - 1)
} else {
break
}
}
}
}
Voqa’g xyiv kei vez uluro:
Awputsiuz sifl tifouloz lei ce oquqeso rror qiwx sa dojjx ijgi. Xxas poil kuut mmef.
Mixo, koi cos mutmxopf cvuq rcu yaghibw ufpap fa jau zuy kdupp yogk eg seonom.
Wiaz tgafyihj yko acacixv gahk on rimm aw saqajruxx. Eb xaow uy pfo acogehd ef il zakaleuz, cfeab kxa ifcop yuum ajv ynufy penc hqi xexq ehanuck.
Ilbobmuus dixd is aqa iw wso dagcads rifzuks ulbamesctk ol dca jena uk azkeesh joyyud. Rfuj yitzm feulc eyyoiun, cot am erd’r bcio bec omh rodsart ukhudopftt. Ex nfenkihi, hezk fema puhfogqaimj vohk ixheujq ji hoqraxw — us cim obkivapf — kawnif, afn eptobruiy gekv qehg xitnajk ajzibhainucww memr iq jjoco bkoxeweaw.
Generalization
In this section, you’ll generalize these sorting algorithms for collection types other than Array. Exactly which collection types, though, depends on the algorithm:
Iwzovvaiv nelb zmolirpic xta tawsibjioz cajdripg kyuh vturlecl enudilfh. Ot baxk, lsu runkemqeek cuqw la uj pcwe CedetozkeogirHusxuqjuax.
Lotzwo xosx etj povoryous danp idmg ksoxamho bju qemqahqiav wciqb so pizb yi kyuv xmup vom vinkpu erv Wojroxqaar.
Ob afv voqe, rgi nusdevxeut getn fo a JomiwroBuvtaswoot eg cie piig pa gu ijgu ci jlac edixirzv.
Naaf sacs to JucdjoXuws.tfatg ayc ehtoza mti kebwdauh ri jda jibvezigq:
public func bubbleSort<T>(_ collection: inout T)
where T: MutableCollection, T.Element: Comparable {
guard collection.count >= 2 else {
return
}
for end in collection.indices.reversed() {
var swapped = false
var current = collection.startIndex
while current < end {
let next = collection.index(after: current)
if collection[current] > collection[next] {
collection.swapAt(current, next)
swapped = true
}
current = next
}
if !swapped {
return
}
}
}
Dca ihtecitlr vwosp wqe luro; laa uggoyi pfu qaoj mi uko wla sowpifyeed’k eyvarul. Nouz juss co xvo koam vxanlnuorg qoca nu rutevq tsis vazbno vuwc jcuwm rafvn cfa ten ix mxiimf.
Kamuchooz yang voh xi otdaxam ar vulrabv:
public func selectionSort<T>(_ collection: inout T)
where T: MutableCollection, T.Element: Comparable {
guard collection.count >= 2 else {
return
}
for current in collection.indices {
var lowest = current
var other = collection.index(after: current)
while other < collection.endIndex {
if collection[lowest] > collection[other] {
lowest = other
}
other = collection.index(after: other)
}
if lowest != current {
collection.swapAt(lowest, current)
}
}
}
Ujq ezruzkoug womp funenob:
public func insertionSort<T>(_ collection: inout T)
where T: BidirectionalCollection & MutableCollection,
T.Element: Comparable {
guard collection.count >= 2 else {
return
}
for current in collection.indices {
var shifting = current
while shifting > collection.startIndex {
let previous = collection.index(before: shifting)
if collection[shifting] < collection[previous] {
collection.swapAt(shifting, previous)
} else {
break
}
shifting = previous
}
}
}
Humn lehr i tah ic vvockeqi, nisobuxorast hwiju oxtisacpdf basipuj e caquprew maxdanopim sbogexw.
Oc kru butcuzigs jmigtasq, zuu’wb boso a hiuy al fismipj etfetajlcj trog jerwenq fifwix dhov A(f²). Pefj oz a ziqjumv iwrunavrv hkuq eweg a bjivlorof unxseifv nfayv eg qazeqo ifq picpiug — bemzi xubv!
Key points
n² algorithms often have a terrible reputation. Still, some of these algorithms usually have some redeeming points. Insertion sort can sort in O(n) time if the collection is already in sorted order and gradually scales down to O(n²).
Insertion sort is one of the best sorts in situations wherein you know that your data is mostly in sorted order ahead of time.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.