 Hello everyone in this video we'll talk about one more sorting algorithm, which is the merge sort So the merge sort has quite a history. It was written around 1945 and commonly attributed to John von Neumann who was one of the basically the founding fathers of Computing as a discipline and certainly if you've heard of air if you're taking CSC 242 hopefully you have heard of von Neumann machine, but it's the architecture that all computers are still based on today So he came up with this algorithm way back when when computers look nothing like they look today Merge sort is a divide and conquer algorithm So much like quicksort we're going to split the problem down into smaller and smaller pieces And in this case what merge sort does is it divides the list you're sorting All the way down until you've got little lists of size one And then it starts to merge them back together and putting them in order while it does that so Here next slide so I'm kind of looking now at the first page of the handout where you have this example here these example values And I just want to give you again the overall flavor of how this thing works Okay, so merge sort takes a list all of our sorting algorithms. We're splitting we're sorting lists here We've got a list of integers Now it's a recursive algorithm and the way it works is you're going to split the list in half and then sort each half Okay, the base case for our recursion is we're going to stop splitting the list once we get lists of size One or zero, okay? Then once we have split the list down down down and they're so small Then we merge them together by putting them in order. Okay, so When we start our algorithm, the first thing that we do is we split it Okay, so we pick the middle point here and we have split it into these two sub lists Now what is splitting look like well in the code usually an easy way to think about it is that you are Just dealing with smaller copies of the list, right? if you think of Python slicing operator where you take say a Sub zero all the way up to a sub mid. That's what you're doing here. Okay so you split and you actually do the splitting is The first step of the merge sort so you're going to keep splitting and you split left and right Okay, so we're splitting and we keep making these lists smaller now. We're going to split this side, right? Okay, and now we've hit our base case If you want to see the order of the splitting take a look at the pseudocode I think it's on page two of your handout So now we've hit our base case right after we have hit our base cases here We know how to sort these things they're actually already sorted 22 is sorted 18 is sorted now. We need to merge right the merge operation is going to put these two sub lists in order All right, so 18 basically they're going to swap places right and here's their their natural ordering Okay, so now that we've merged here right we've hit our base case Where we actually come back is up here, right? This guy gets split and merged back together Okay, so now we've if you think about it. We've Sorted these two guys, right? We've sorted these two guys and now we're going to merge them back into a four element list And when we merge them, that's when we put them in order okay So now look at where we started we split here we split here and we Then started ordering them back together, right? So this is the ordered value of this This is the ordered value of this we merge again and we get the ordered value of this Okay, so what I invite you to do is fill out the right-hand side here What what do the operations look like it's going to kind of mirror this okay? So take a second and do that I'll pause for just a second to let you kind of work it out And then we'll fill in blanks Okay, so if you split You split this way again. We're not splitting on a value. We're just splitting on a position. We take the two sides of the list Split it again until we have lists of size one or zero So you will wind up with a list of size zero at some point if your Initial list has an uneven number of elements, right? If you have an odd number of elements at some point you're going to have a list of size zero Merge this side back together Now we split this guy Merging back together right and now we're ready to merge these We get this okay, so now we have sorted our two original sub lists So what's the final step the final step is going to be to merge these two and as we do that to put them back in order Okay, so that's the essence of merge sort I very strongly recommend checking out both of these Visualization tools. They're really neat. They they try and capture it Especially this first one help you walk through some some more examples. Okay, so let's go over to our handout and Let's walk through the merge operation So if you're looking at your handout, you're gonna be on page three, right? This is the table that we're looking at on the right hand side I've copied in the merge sort algorithm, which for you is going to be on page two At the top. I've just pasted it over here. So so we can all be looking at it on one screen. Okay? So Here's the merge sort algorithm. We've got our base case first Remember it's a recursive call. We're gonna keep making the list smaller until We're trying to merge sort and is greater than one or excuse me less than or equal to one So we merge sort the lefts we merge sort the right and then once we have merge sorted them Now we need to merge the sorted sub lists together and that's what I want to walk through the merging operation It's actually, you know, it's one while loop It's actually not too bad. It may seem a little confusing, but once we walk through it, hopefully I'll understand what it's doing Okay, so let's look over here and fill in this table and kind of walk through this teal block because this is the merge operation And it's the kind of the key part of all this Okay, so we're at the point here where we've sorted our two sub lists So let me go back to the slides. We're basically at this point right here Okay, we've sorted our two sub lists and now we need to merge them together So that's what I want to illustrate for you Okay, so I've got two sorted sub lists I'm going to call them the left sub list and the right sub list and you can see they're sorted Let's walk through the merge algorithm Okay, so we've got an I, a J, a K and they're all initialized to zero Okay, so K is going to represent the place in the merged list, our List that we're kind of like putting our results into it's the slot. We're going to fill in Okay, I is a counter for the left sub list and J is a counter for the right sub list Okay So what this loop does is it walks these two Indices it's not a counter. Excuse me. There are indices. It walks I and it walks J up these lists and it compares their values and Based on the result of that comparison it decides who to put over here, right? Okay, so while I is less than the length of left That means we're going to walk all the way through this left list and while J is less than the length of right We're going to walk all the way. We're going to walk one of these pointers at least all the way through their sub list Okay, if left sub I is less than right sub J. So is this element here? less than let me Put in some shading here Okay So is this element here on the left sub list less than The value on the right sub list. Well, yes, it is Okay, so what we do then is we say a sub k This slot gets the smaller value, right? So the smaller value is 14. It goes over here Okay, so we put 14 over here. So what gets included? We include 14 from the left sub list Okay So what happens next? Well now we're going to increment I Okay, so we're going to move I up a slot and we're going to move K up a slot All right, so let's do that on the next line. So we've already figured out Where 14 goes? All right, so K is Now here, right? So now K is always so for every iteration of this loop K is going to point to the slot we want to fill in in the merge list I is the next thing we're going to compare in the left list and J is the next thing We're going to compare in the right list. Okay. All right, so iteration number two if left sub I is less than right sub J Okay, 32 and 23 well 32 is not less than 23. So what do we do? We trigger our else clause here a sub K gets the right Value right so a sub K is going to get 23. So we wind up copying in 23 from the right sub list Okay You then increment J and increment K again. Okay, so In the next iteration J will be here I will be here um Basically, also you can see that anything to the left of these guys of these indices It's it's done with it's already been moved over here Right, so now what are we going to compare we're comparing this guy In this guy and we're going to fill in the slot. Well 32 is less than 41 So 32 goes over here Because we took it from the left sub list. We're going to move I up a slot J will stay the same in our next iteration and K will move up a slot. Okay, so we're in the state where we've got This right now we're on to the fourth iteration of our loop and we're comparing these two elements So who's the smaller of these two elements? Well 41 is okay, so we copy over 41 from the left sub list Let me fill this in just for from the left 41 from the right Okay, and then what happens? Well, I stays the same J gets incremented by one and K gets incremented by one Loop again Right now we're comparing this one and this one All right, so we're at the top of our y loop if left sub i is less than right sub j It is not so we copy into our merged list a sub k right Sub j the right value. So that's 58 All right, so we've taken care of 58 So we increment j by one We increment k by one moving in over here And we loop around again. So i is the same fill in these values That we already have All right, so each line here represents a single iteration of this while loop What are we comparing now? Whoops, I didn't increment j properly We're incrementing we're comparing 67 and 85 well obviously 67 is less here. So we copy 67 From the left Goes into our slot here. Yep, I forgot to fill this in Okay Now we're gonna move k up a slot Uh Because we copied i i gets moved up a slot and j is the same All right, let me try and get everything on one page here. There we go Oops, please ignore More Stuff over here a little extra. All right, so, uh, where are we now? We're on the next iteration. We're comparing these two guys Okay We already have our partially sorted list So who gets copied? Here 76 or 85 or 76 does according to the logic We increment i Okay, so here's an important point. We increment i i is now kind of like It's gone off the edge. He's over here somewhere right i has moved over here. We've already done everybody Um, the only thing left is there's still some elements inside of j Okay, so i let's look at our loop condition while i is less than the length of left Well at this point i is going to be over here somewhere. Uh, i's going to be Five or four excuse me index four four is the length of the list. This loop will terminate Okay, this loop will terminate. So what happens? Uh, we've wound up Now in this situation where uh, we've completely exhausted one of the sub lists Let me turn There we go. That'll help that'll help Okay, so we've exhausted one of the sub lists, but one of them still has something in it, right? Um 85 is still not been copied here. So whenever this loop terminates you have another loop Okay, one of these guys will still have elements So all this loop does is it's going to find the one that's still got some data in it the right list And it's going to copy all of its value remaining values into k Right, so if this had like 85 and then 100 we're going to put 85 here and then 100 and then 120 whatever happens to be left in there, right? Keep forgetting to fill this part in And that's okay because These the sub lists are sorted, right? So anything that happened that may happen to come after 85 is already going to be in order So we just got to copy it on All right, so that's the intuition behind the merge operation Um and merge sort we're splitting it splitting it splitting it all the way down till we have lists of length one or zero And then we merge them and here's the merge operation. It's actually relatively simple how it works Once you can wrap your head around it All right, so let's answer some questions here about merge sort In the worst case How many comparisons are made in the merge sort function on a list of length n? Okay, so there's going to be m plus one comparisons Right and plus one comparisons at a minimum These guys are like, you know, you have to look at each Uh item in the worst case you have to come and we kind of saw this was the worst case here, right? Um, actually, I'm sorry. It should be n minus one comparisons. So Um, and then how many movements do you make or you make n moves, right? Move is a copy from the left to the right, right? This is we're just talking here about one comparison um How much in the merge operation? Okay so supposing I should change this in the merge portion Of the operation of the function. I'll change your worksheet. So it says this to begin with Okay So uh n minus one comparisons with n moves. So the that's this portion of the operation All right, supposing that we start our merge sort with a list of length n At most how many times will we have to split the list? So how many times do we have to split a list of length n? Well, if we're dividing it by two Every time that looks a lot like binary search, right? So at most we are going to have to split it log base two of n times All right, so we have to split this many times. This is how many recursive calls Or yes, this is how many um times we call the function And then we have to do n comparison or m minus one comparisons n moves This is going to be yet another like quicksort A big O of n times log of n algorithm, okay So besides the list a how much additional space do we need to run the sort? This is maybe a downside of merge sort at least the way that we have it You can potentially need a lot of extra memory to keep The sub lists, but there are ways around this, right? So a good efficient sort algorithm does not use much extra space at all So it's highly memory efficient, but if you're not clever in how you do it This algorithm is pretty I want to say kind of clever um The fact that it's returning a value here means you're Going to be returning a copy or at least no actually not in python in python. You won't this is a pretty efficient algorithm um If you were to try and do this in java the way we have it written it would not be so efficient All right, suppose you have a list containing blah blah blah What is the sub list that is to be sorted after three recursive calls to merge sort? Okay, so i'm asking you here to kind of fill in This chart with uh the list that you see here and trace it like Which list are you going to be splitting after the third recursive call? I'll post an answer to that and the solutions to this chart in general All right, so merge sort quicksort and merge sort are our two n log n algorithms And they they have a style to them that is somewhat similar It's both divide and conquer in quicksort You pick that pivot value and you put it in its spot And then you guarantee that everything that the partition to the left of that pivot and the partition to the right The left is less than everything is less than the pivot in the right Everything is right and then you do quicksort on the left and right half merge sort You just divide straight in the middle pick the middle merge sort the left and the right And it's the merging operation when you recombine them where you do all the work. They're both divide and conquer um But in practice merge sort is used a lot more often And the reason is because it's more resilient merge sort is big O of n log n Regardless of the data that you're sorting if you remember from quicksort There are some cases where quicksort can look a lot like insertion sort if the list is already partially sorted You lose a lot of the efficiency of quicksort merge sort doesn't care. It's very steady merge sort is also a stable sort so everything's going to be in the same order that it was inserted And also because so because of these properties quicksort is uh, I believe it's not a stable sort, right? So because of these properties most built-in sorts such as pythons sorted and list dot sort They use a version of merge sort. All right, so that's it for merge sort. Um We'll have I'll wrap up in just one more video that kind of summarizes all the sorting stuff and what we need to know