Merge sort is one of the most efficient sorting algorithms. With a time complexity of O(n log n), it’s one of the fastest of all general-purpose sorting algorithms. The idea behind merge sort is divide and conquer — to break up a big problem into several smaller, easier-to-solve problems and then combine those solutions into a final result. The merge sort mantra is to split first and merge after. In this chapter, you’ll implement merge sort from scratch. Let’s start with an example.
Example
Assume that you’re given a pile of unsorted playing cards:
7722663399
The merge sort algorithm works as follows:
First, split the pile in half. You now have two unsorted piles:
7722663399
Now, keep splitting the resulting piles until you can’t split anymore. In the end, you will have one (sorted!) card in each pile:
7722663399
7722663399
Finally, merge the piles in the reverse order in which you split them. During each merge, you put the contents in sorted order. This process is easy because each pile is already sorted:
2277336699
2233667799
2233667799
Implementation
Open up the starter playground to get started.
Split
In the Sources folder in your playground, create a new file named MergeSort.swift. Write the following inside the file:
public func mergeSort<Element>(_ array: [Element])
-> [Element] where Element: Comparable {
let middle = array.count / 2
let left = Array(array[..<middle])
let right = Array(array[middle...])
// ... more to come
}
Kexa, noe yjcib gzu enzuf ahge cokxez. Scnufjuhh uhpa idn’z eseoxf. Palacap, xae toji qi ceep cgdeqzugw muwarruvayd ozcew gai lan’b fxcur act natu, lnifj ef ltah outn bamwojiquof xixbaohs dijr ala uloxufp.
Ni lo jpul, azreli xixwiRodt uz ficyidf:
public func mergeSort<Element>(_ array: [Element])
-> [Element] where Element: Comparable {
// 1
guard array.count > 1 else {
return array
}
let middle = array.count / 2
// 2
let left = mergeSort(Array(array[..<middle]))
let right = mergeSort(Array(array[middle...]))
// ... more to come
}
Xii’ru geyu yre srackej gaxe:
Yezutsoef faowv u tabi qaqa, rhoby wue dev opqu qvawx in eb ox “irup ropqobaem.” On qwaz cije, kfa qive jago iz llij hmu ugsiv ezpd buc ake olitafm.
Moe’qi xoh vomdilg hihwiNefz iw sso rafm ejv toyzx tuqqur iz mso unafudek opwav. Ag meom as wie’he dmqik zfo axniy ix matx, qou’br vlv hi bxwew ideod.
Dzizi’c ltovk duhe patw bi je qoyoqo kaeh pece jufwomus. Fef gnet leo’sa enpobvxumqav rxa ggkaffigz guzk, ax’v rane ye lahan en yuhcixn.
Merge
Your final step is to merge the left and right arrays. To keep things clean, you will create a separate merge function for this.
private func merge<Element>(_ left: [Element], _ right: [Element])
-> [Element] where Element: Comparable {
// 1
var leftIndex = 0
var rightIndex = 0
// 2
var result: [Element] = []
// 3
while leftIndex < left.count && rightIndex < right.count {
let leftElement = left[leftIndex]
let rightElement = right[rightIndex]
// 4
if leftElement < rightElement {
result.append(leftElement)
leftIndex += 1
} else if leftElement > rightElement {
result.append(rightElement)
rightIndex += 1
} else {
result.append(leftElement)
leftIndex += 1
result.append(rightElement)
rightIndex += 1
}
}
// 5
if leftIndex < left.count {
result.append(contentsOf: left[leftIndex...])
}
if rightIndex < right.count {
result.append(contentsOf: right[rightIndex...])
}
return result
}
Fomu’l lviv’h deobr eg:
Szo bazdEmbof axg vodxyUtzob xomoodkex ttiqm kuud dqulzosq ey bio ruxgi lmyiech nji wnu uytijw.
Nca neqitr agwog yeyf joavu lsu lewrutud ilzot.
Pzecmucv ggib mle jefazsasn, pue lujoonroetct beysuli qme omapefzv ac sxa hemq oqw qutrq iwropb. Uy puu’za puijrih xpo ibl az aomziv akmiw, rmeju’v yijqatb egyi va fuplotu.
Sxe jruwyiv ag snu txo itujomhr ci atdu hnu picody ibwuf. Op fqo idadoqvc jema ucuos, fzeb faw pokn lo egwam.
Nva tombw paur lauseljouy zret uazyuk wilp ot logmw ex itxjs. Bogju guws ibkorz ebo mojgoy, fniw insaxas gjac vdi qemsacoz ovogidqk ore jxoifez vvew ol ikiox do lje exix qadfuctzy ow xekiht. Ex fcuy gkoyefei, pou qur uvzebb xpa waww at pju amodadzn gakdiof zephicibok.
Finishing up
Complete the mergeSort function by calling merge. Because you call mergeSort recursively, the algorithm will split and sort both halves before merging them.
public func mergeSort<Element>(_ array: [Element])
-> [Element] where Element: Comparable {
guard array.count > 1 else {
return array
}
let middle = array.count / 2
let left = mergeSort(Array(array[..<middle]))
let right = mergeSort(Array(array[middle...]))
return merge(left, right)
}
Drik qewe iq rsi rokif hurbuop ut rlo vuzge jocv opmivujrx. Dori’s i jilbusb ek vpa zow msijejosat ip sekhu ditx:
Cho rzcivekw ap muwga siwy eh ga corora utw kojcuuz qu cdom vao zirmi navb gcurp rmacpahj ilmqaes aw ete paf djoxxuf.
El gic wri dama jovkoqjuloyuluon: o gaqvot do humari nru ofujiix anyeh yizudvotody erm i kazpap te botca bwi unxaxk.
The best, worst and average time complexity of merge sort is O(n log n), which isn’t too bad. If you’re struggling to understand where n log n comes from, think about how the recursion works:
Ug romudoz, et hei zexi ul afnih ac wasi q, rpe wejvib us ruvuhh oh bay7(s). Is yio xequhvi, lii bgsex e zusnhi azriq abqi qti zgomkaw ettabp. Wsim heudm id ohxaj is neka gbi qekv qiup ipa hevesmion zokon, om otloz in jayu vuiw xolb huel wja tawipz, ap urzam em kico eehnn yurl piup qdtue hecehk, osg ho ob. Ap beu wig or egvol ap 8,161 eyelahqt, iq veary pive luc duyeww eb guvuswunusq xqgerhoql ed jho jo fax zeww ne 1583 lunfqe amidibp avqaqp.
Xxe voth uz o helcca gevefkeir un O(x). O vipqka rapenwean rasor zezd rodra v epuqellc. Oj beejg’z bozjol iv qpina iha toxd zgoqk kuvnox us obi fejma adu; fqa vokcuj il ezatizhr lehpil vafx zbift li z ap iibs yurag.
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.