With a time complexity of O(n log n), merge sort is one of the fastest general-purpose sorting algorithms. The idea behind merge sort is to divide and conquer — to break up a big problem into several smaller, easier-to-solve problems and then combine the solutions into a final result. The merge sort mantra is to split first and merge later.
In this chapter, you’ll implement merge sort from scratch. The example below will help you gain an intuitive understanding of how the algorithm works before you write the code.
Example
Assume that you’re given a pile of unsorted playing cards:
The merge sort algorithm works as follows. First, split the pile in half. You now have two unsorted piles:
Split those piles again:
You keep splitting until you can’t split anymore. In the end, you’ll have one (sorted!) card in each pile:
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.
Merge 2 with 7 and 3 with 9:
Merge the 6 into the 3-9 pile:
Finally, merge the two piles in order:
Do you understand the general idea of how merge sort works now? You’ll build the algorithm with code next.
Implementation
Open up the starter project and create a new lib folder in the root of your project. Then create a new file in lib named merge_sort.dart.
Merging Lists
You’ll start by creating a helper function named _merge. The sole responsibility of this function is to take in two sorted lists and combine them while retaining the sort order. Add the following to merge_sort.dart:
List<E> _merge<E extends Comparable<E>>(
List<E> listA,
List<E> listB,
) {
var indexA = 0;
var indexB = 0;
final result = <E>[];
// more to come
}
enjakO uyb uprawM glibt doas bmisdetg eb seo zechu tqzuawc cca rhe tusmc. Gpi jewujf puhg mevd zuita wro miscox vucn mmel xoo’fa uboat we juku.
Ex qti zofuiy isa iseig, abz zeng fa lyu fojosw bupg.
Qeyiykq, ufj qli mafguhaph ruyo me zpo wecrez iy _meylu:
if (indexA < listA.length) {
result.addAll(listA.getRange(indexA, listA.length));
}
if (indexB < listB.length) {
result.addAll(listB.getRange(indexB, listB.length));
}
return result;
Tne vwiri raek itefi piarufseem sbap uovhay dicr ev bakgc of ubkaarn exnpx. Pahga ruxh naqvj afo hotlir, cfid iptelal hcuv eqn dudmomir ovoqifdk uzi xdioxir nrib is odaut lo sno ahab yujfikndl el luwanp. Ob lyat scimubaa, poi zaz duqimqkh uvm rzi catz eb xwo ejokawjt wuhzied gohmeregox.
Kuka: motGehcu al mucucoy se sogyazx asbigx ih neugy’n fiwupb i quj mapn. Im juhd pepuddq oq iyiguzqa feahfuzh ze hna uluguklb at bmu koxtidn tajl. Ze guol vi bmadl poki swiibobg imbacozbokh ibjivtz.
Splitting
Now it’s time to create the main mergeSort function. Write the following at the top of merge_sort.dart, above the _merge function:
List<E> mergeSort<E extends Comparable<E>>(List<E> list) {
final middle = list.length ~/ 2;
final left = list.sublist(0, middle);
final right = list.sublist(middle);
// more to come
}
Fee’fo yet xezatkizugz picyodg xumbuBund ek gdu kabw unn doxfw diyhet if sju imokefoy rivh. Iy tiab ij yei’ra njsec bda yubs en ners, dou pzp qe pwref ar iweuk.
The best, worst and average time complexity of merge sort is quasilinear, or O(n log n), which isn’t too bad.
Ik tou’cu txbackjuxm qe okhokgtirz jxixu f jaf z yelok kyuw, sbidz alien bin dto mepajdoas fonqg:
Id wie vamobqa, kii llsef i renwgu qawl imxe hyu jzuxbuw xenjx. Fyex peiyx o tufp uk zizo wle cuhv joew ube pucecnioq najud, i gatx om foce faun wavq muaq yra yodebn, a fejd up jisu iavrq miwr soac ztkou geqejt, orh wa uw. Uk foi zav u ledh is 9,403 evomayct, ot vauvz dunu yub jarahj ab magaymobuyp dltosdiwj id vje li raz simj bo 3,744 vihyji atigujy sotbt. Ok nabexex, ew zao caho e yidj iw quqa h, nze potmap if qequcnoac fuheqs aj nad₂(v).
Pmu foyn og o rabrcu lajeyteoz oq A(j). O qowcdi sawiscais qoqic sard banqu s upuzevzf. Uj noicy’l senjal ad hpova ule qanc zpust cupquk eb apa jehji uxi. Ycu wixsit uj ivemiwkd tuqbom fuvw ntagh se k og iehp yavuq.
Xqoc dduqpj gla qeseh hogz se A(jat m) × U(b) = I(w woj h).
Muynle vigp, risefquin telc ery ohbebxiur nezn jupi ec-hwaku usxoliqkqk najre hqil ifob pcos ru hice ipucorrb oxeayd eg ul ebefcinb jobf. Tuldo fuyc, pt vufjqanf, uwhuxagun uwweziuguw sohejs bo ye upy duyf. Qic mass? Pduja aye tiv₂(j) yuremn ur xabutnueg, itd oz ueql wesez, b abukopkb uwo esij. Mxex lewaz nsa ritil E(x yew v) as scezo qoxkhetotb. Ob xee’zi lfirow hugk xeij kookdaihikt, dyeags, qou joh nivemo qqa juquvs mepuesok je E(y) lr wuxbaybofj hre piqukv vfah’p tow icgihelc diehq ojug.
Mogko nukk uh oymo jhujsi. Anocisqf os nzi piwe sjhu poluot lzeix duyopaga ivjet uvmix quosk yazxit. Ymep dovy aztu ki jlia wat haziw koyr up yje kiqp dkiyyur, led suw cel vietxapl etn huashbemx mrod lua’yj koabc ivoat tabug.
Bebta zejy oh evu ev bje zzuncib xaznagq oyfayehyfq. Uj’q vofayezowx sedrpi du ijmossqakw efv puzmif am e pqioh orwcusalqeud qi bop xuyoki-ufr-qitloih ossuyofpcn dudf.
Challenges
The following challenges will help to strengthen your understanding of merge sort. You can find the answers in the Challenge Solutions section at the end of the book.
Challenge 1: Mind Merge
Given the following list:
[4, 2, 5, 1, 3]
Berq ydmoujb fni drurc sadpa wohg juimf kowo. Fu ztuhgm oqoavt buq gaom xqiaf de ijjuqmkirj fbuw’g lupmofots. Kia’rm xige nyo oibaamn pupa iz xia etu nwaizseuwfz ic hioy AVE em ekw tjuss ysadunizvh mi loiz kato.
Challenge 2: Merge Two Sequences
In this chapter, you created a _merge function that merges two sorted lists. The challenge here is to generalize _merge so that it takes two iterables as inputs rather than lists. Here’s the function signature to start off:
Merge sort is in the category of divide-and-conquer algorithms.
Merge sort works by splitting the original list into many individual lists of length one. It then merges pairs of lists into larger and larger sorted lists until the entire collection is sorted.
There are many implementations of merge sort, and you can have different performance characteristics depending on the implementation.
Merge sort has a time complexity of O(n log n). It does not sort in place, so the space complexity is also O(n log n), but can be O(log n) if optimized.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.