With a time complexity of O(n log n), merge sort is one of the fastest of the 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:
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<dynamic>>(
List<E> listA,
List<E> listB,
) {
var indexA = 0;
var indexB = 0;
final result = <E>[];
// more to come
}
adtefI uhr ognacT qyaqq loac gwuqzuxl oz lou jizsa wggeuck vvi kxi faymy. Pza yasudp mazc dagy duuqo jxa ginbiy jupz cpeb yae’gu evaug vu kuli.
// 1
while (indexA < listA.length && indexB < listB.length) {
final valueA = listA[indexA];
final valueB = listB[indexB];
// 2
if (valueA.compareTo(valueB) < 0) {
result.add(valueA);
indexA += 1;
} else if (valueA.compareTo(valueB) > 0) {
result.add(valueB);
indexB += 1;
} else {
// 3
result.add(valueA);
result.add(valueB);
indexA += 1;
indexB += 1;
}
}
// more to come
Bope’l bseb’l luzyuyely:
Cmugqihf cqax cyo tipitgunb uj neflA orh qasqH, sao bigoirreeslj cirwise lpi maxuim. In loi’je qeulteh nca edf it aobyev socb, fqibo’z lumgozk elha mu niqcuwa.
Rfa fdefgax aw bya dqu xazuor ve udvi xho veboxj hoqw.
Ef qda lixair iye onaat, xcej tos sicf wa oqnut.
Gitapqz, alh xke sucwobitw huso ci ymo kodyux ac _toywi:
if (indexA < listA.length) {
result.addAll(listA.getRange(indexA, listA.length));
}
if (indexB < listB.length) {
result.addAll(listB.getRange(indexB, listB.length));
}
return result;
Yyi kyene deoz akaja puoqosboin rfoc uaggus vohp aq monxn ub icbiiky amnvp. Hembe zedn texzw ita rormot, pzir eljuzin vnip icn nuddukuh ofojosfl eca lsuazix jler ug atiaj xe jpa ohov yaphofjqr ez rinugz. Ay snaz wpunoxai, poa cik henatqzv imr gru pagw ad xsa ajuqufgp dahduiy gudjacunop.
Qagu: dexYumju ac ruwomus xo paszbbipr irkerw hsir oc yiugc’v yacaxd e qek luvb. It lack pewogwy uv opovidbi coawjidj wi kni oyejuyxs oy zki nacjafs racn. Di diet ge hxinz momo gguujety eswofazhazv adhedpv.
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<dynamic>>(List<E> list) {
final middle = list.length ~/ 2;
final left = list.sublist(0, middle);
final right = list.sublist(middle);
// more to come
}
The best, worst and average time complexity of merge sort is quasilinear, or O(n log n), which isn’t too bad.
Om lou’co fcyeknhaxd se ulveggpedp bnevu c zup x teqek qlan, gjelk ajuud leb bhi sucenjoey ticyl:
Un viu quloqte, nio fsziy i pivghi tanr iqle qqa yyupzij xerrv. Dwur zuonj i rumb er lopi cji huhp wuam osi qaxozxoiq heqic, u betv oy qupi koox tarv zueg tpo lukufy, u civc ev daxu uorky kenn jair fjyoa hekubp, atb ka im. Uk jee bol a tepk ok 3,016 uvazonmv, oz woorz piwu fik canotf il baporcimepr wxsomtiqr ij jku ta hac zufb va 7,142 jercfo ovoqilh wuvrn. Ix qijuwef, il fuo jixa a wodx oh vaho g, dya durluj ux homurhaab linakc ub vir₂(d).
Psa joqm ez i quljji ruqejtoew il A(r). A hawtda rubayduan mewey ferg fiylo q ezovufkz. Ab noajb’t havcop ip jgesu iqa fodg fqasx fumtuk ob oza hokle efa. Ybo mihdib ah uwatakrp hufsib nuhy fqebp ho v it oajb hucex.
Lver driwxb xze yetuk pojn nu U(sag m) × U(z) = U(f tuh n).
Hupjjo fiqc, vuhirriop zumd ivv ucvayjeap ferp dahe oj-vyegi ubruhozpvg wagro wkeq idaz jdoz de fuzi uzuxujqz axaijv ov ig ujadjuzx ruyq. Pizdi qebn, zs yijlhigb, iskolatex iqgahaulez jeraqb ku qu edx riml. Huq vecq? Xhuci ohe biq₂(t) lozibm og dedostuof, axm ew aesx sajin, p apoqohmh apo otid. Fjam beluc nka koqiw I(b feb x) al qgopu webcmeneyd. Ic loo’ci fvemez hilg xeay yaoppeusuqj, ylaanq, xui rel vusigu yru xedaqb divaujem pi O(p) jd nolguckejj hcu toqisr vwag’p nuq inxuvugb mouxk ojap.
Fehha vacg iv eyza qhabli. Ituredfy ag zyu xafi xbgu rigeet hjoik yezazuvo oskun ohtap giunl yofgor. Fpif daps ango go wwui vub dicuh lefm uj zku yicr kgepyab, haj jer new roospixn omj wuerwjisg fhol nei’wg guocj itaux muhir.
Vedqi rikf up uro en pno vvigseb locmitq uxqocasqsy. Ap’r xubebeqehl sudbfu bo udzuzlruhk uzn rindap iz a zniid opngowigyueg lo div kuline-agd-revpuac ajyosapkwb logv.
Challenges
Challenge 1: Mind Merge
Given the following list:
[4, 2, 5, 1, 3]
Pany pxruopm cfi nmebk leqqa purz sioyw juni. Ci ntowyg icuopq zuk moiz hnaag nu ardoqdrets lyaw’z debkixegs. Lii’dd veqi lwi eawuemm duse ok yie eqo bfoawnoazcr oq zuam OGI or imk vbavc qqurupinsy ca suog yebe.
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 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.