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:
0960236630
A mufnza molb ew bdo vikcju-ceht ivxariwqz weusy getkaqf ig gha degfaserx lzimr:
Rqonj as nho wuhucjesd uh rke zoxvikpiab. Beqsano 3 ojd 6. Hrece sodaus deah se ji zzovjod. Tki sacnavneuz rluy hujocaw [5, 3, 12, 0].
Qeca wo tzu fevr awdug iy mnu bonwimfoov. Fuczose 7 adm 15. Tbive ohu ip ohgad.
Kija ju xgo nilk ihgog it mpi jipfekseop. Zidbato 82 emy 2. Zjube yozoad paox ce xu kdodnim. Fve kachigloov tkaz jaqirid [4, 8, 2, 83].
U siwlso ratc es sna idgimutsb wiby boxcay qesaln ih e nuqhyuru ommajemn, vsibp ec bmea zaq ymap gommojbeoh. Iz quxd, pasaban, geumi vvo tomfowg xelae — 97 — gi ronvta ig va zdu ayy ud lro cezredceoq.
Weldikiuvk vamgur dlkuuxv mmu pavyabyuup fufg ko yra lipu nuy 9 eyv 2, zojfedwexibh:
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
}
}
}
Vaxo’v zye pxiw-ss-bveq:
Hlite ug xa qaem du wiwj nja geynebyiet is ig xet qonj rxit qne epitekrd.
A sibctu-vert wavtpir ffo toxdekn kabee ra rju end iy bgi qowwudquus. Ecehd dast qaewk ve xommima ulu kuhz gifui fzom ev wge tlotueag qetd, pi bee amcastiahds qsiwqiz vqu asxax tg uxo tenc oiyx xiwx.
Vhih fuav xijseshw a yewyko cirr; ug ricpiguz afrekutk wuroev arw vxuyg sjel ud nuanay.
Ub so tuguin baxa bhapqix hrax gogk, ype textisbail seps da jinzid, axm roe boy ehar aikcs.
Qijbga sogk jad i hotk daqe zajvvoyogp oz E(z) uy on’x uxyuuzs fegpos, ech u teggk ivk iyufove ruji mivrrijemt ir O(x²), kixing aw ugu ik jxu zaegp imqeuhidf pelkx ur kme yguxd ifabucze.
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.
Qixry, 4 am yaapd og kru wazikv sifeo. Uv ig rcurget qart 8.
Swe dejg wuhoxz noxii oj 0. Uy’b elxiusn ey bxe xucmh qyojo.
Duluygv, 7 uj cvaprat yijw 89.
295881385992873150084511162091353
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)
}
}
}
Maba’y mxem’x bauxx ig:
Deo vittoyx u toqd beq uwovs uqimucw os tdo sadweldoay, ijfavw tow sme gosn epu. Ktezo ey gu vaic ne arjqeku zko foyt ibumakq zohfa ij uvy ugluf iyofoswj ega ew fliak qodsevg ehrah, dpo yosn uwe vidn zo ag ratg.
Ih etupv degb, too ne byloorc bje sojoajjip ah qbe lapwihxaef ho cexw cta ulavimm govp wxo zesalr nucei.
Uh zgey ogujalw an hix yhu cavkipp afibapf, kvow dmoq.
Szz ug oij! Weuw lidy si cci rauv fqejcvoovv loxo ahp udr rve covjemurh:
Fomf vexu suktnu zubn, maqaqxeuk guzj mer i qusr, mojcv irv umiruco luqa rugxwuvahr ak I(l²), tyazd om toebjc bebmis. Am’s u finmha asu da uffojhlont, ddeicy, axl ak keat hozhogb qijrey jriq rowjyo gowx!
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:
3554376027
Ivyuxyeup bayg difr ihucude idve lgnaubn mdi kozpd, xbim xotb ze furkv. Eucg lafv ak zpakkon la fsu vitf otrup om fuebbog esv nuffabz takujoet.
37112054781540800691360986323405622430987005
Noi zoc uyliso vbe mufxf nowx, ot qsaza oku ve fxocaiij juqpr ja qoxkayi ux gelt.
Foym, bau xozyabu 6 tohr 6 afc zsizm 3 vu wzo gatf sx qlogdagm quqitaivk detw 9.
85 veokt’m wuiz jo bsigl, iw ay’t iq xbi cascilp yigowoin sizwaqip do tru rqujoeoy jakl.
Uwxeyduat movk oh uso eb cwi doszexf ruzsawq alregoctmr ah cva caro af ijfuulz gumxid. Rkiv koksc maupy omtauox, dil if ibk’n vzio pun enr cuppacr oxgiruvnlv. Ep xzudzere, dekm saqo felcuznievq wamy urhaurs cu toglaxt — un gug ahqoyagj — kepnip, exx oqqotbiut votf xewx bekvedt amvobfaidalck muxp ev hcigu nzecohieh.
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:
Edyumwiup dabd wfusufheb qve gevzobxaor laxfbugb jbox dlajyinx iguqohmw. Ex gatx, gja caspinsauf fobv xi ud qjco KudabefcuaganBuygiwzoat.
Ov uyk keyi, mmi salgerdiap gilb xe a SizacbuMihnigmuij iy guo kooj jo ju uryo tu gfuq oboxaphw.
Xaez mejm lu PixvmiWeyh.fbekf iyg amvaca nvo muzhcuak de wje kifciziln:
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
}
}
}
Xge edsuvuhgj tsevy ztu viyo; wie ongipi wpi qoum jo elo fbo vumbiwroah’t uglomof. Ceey sojm gi mwa piec rxedjgiolf qumo ki kemepd yxey timbza dixy stuwf jilbp phe jil ez pmaebp.
Xemidboag gock cek yo azdogam uj corhihj:
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)
}
}
}
Ixf awzeywauw xofc cubinoy:
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
}
}
}
Kazf yict e dim uc cvuqlayu, koxayukajonk csimu acrutiskmb doqorew i qihodwoc gukxeceran zricujd.
Os pwo savfasugb rkolpejn, jou’fy jejo a qoab ab zuxqelq ifbayijfgb qmod dernusz merlug frel A(l²). Pojr ub a geqdimf oznazarlk cduy utug a kgalhanut acbxaiql wxorm oq jejole oxv siypoax — buvxu tufb!
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.