 Hello and welcome back, in this lecture we are going to look at a new technique for sorting, this is called merge sort. Here is a quick recap of some of the relevant topics we have already studied, we have seen what the sorting problem is, we have also seen some motivating examples and we have looked at in some detail at a particular sorting technique called selection sort. We have tried to understand the intuition behind selection sort, seen a C++ implementation of it and also did a very crude and high level analysis of its performance. In this lecture, we are going to look at a new sorting technique called merge sort, specifically we will look at the intuition behind merge sort and we will look at some animated examples. Now recall the intuition behind selection sort, we had an array of integers which was unsorted and we wanted to get them in a sorted order. In particular if you recall, we wanted to get them in a decreasing order. So the way we went about doing this, start with the unsorted array and then solve a very small part of the problem, specifically we found out the maximum element in this unsorted array and put it in its rightful place in the sorted array. Once we had done this, we were left with a similar but simpler problem to solve. Why was it similar? Because we still had to sort the remaining marks and why was it simpler? Because we had one less marks to worry about. So you see the overall principle here is to take a larger problem and sort of break it up into slightly smaller problems. In this case, we found out the maximum element in the given unsorted array and then we got a slightly smaller sub problem in which we did not have to worry about that maximum element. Now this general principle is actually a general paradigm in computing. When we are given a large problem to solve, oftentimes we can solve the problem by decomposing the original large problem into several smaller sub problems. If each of these sub problems are themselves instances of the same larger problem but perhaps with reduced size of the input, then we can solve each of these sub problems separately and often using the same techniques that were used to address the larger problem. And finally, once they have solved all of the sub problems, we have to combine the results of the sub problems to obtain the solution of the overall larger problem. So this technique, this overall principle keeps appearing several times in different computational techniques and in general, this is called the paradigm of divide and conquer. We divide a large problem into several small sub problems such that we can solve these problems and by solving the sub problems and combining the results, we can tame the difficulty of the original larger sub problem. So let us see if we can actually sort a given array of integers using this notion of divide and conquer. So here is our array of six integers which is unsorted and we are required to sort them. So what we could do is, we could say well instead of sorting an array of six integers, let us first divide this original problem into two sub problems where each is an array of three integers. So here, I have just taken the top three integers in this column and formed the first array over here and I have taken the bottom three integers in this column and formed the secondary. So now I can say that well instead of sorting this larger array of six integers, I have these two smaller sub problems and can I sort the first half of the array and the second half of the array independently and separately and somehow can I combine the results of the simpler sub problems to get a solution of the original problem. So basically, I would like to sort this sub array into its sorted order which in this case happens to be the same as the original order and I would like to sort this sub array by some means into its sorted order. Here it is sorted in decreasing order and of course, here you see that some changes have happened. 27 went to the top and 25 came down and once I have these two sorted sub arrays, notice that I just cannot put one sub array by the side of another sub array and expect to get a sorted array of size 6. Indeed this is a sorted array of size 3, this is a sorted array of size 3 but when I put them together, I may not get a sorted array of size 6. So I will have to do this additional step of combining these two results. So we will call them merging two sorted sub arrays to get one sorted array of size 6. So what were the steps that we used in the technique that we just discussed? We took an array of size n and we divided into two sub arrays of size roughly n by 2. Of course, you would note that if n is odd, then the two sub arrays will not be of exactly the same size but their sizes may differ by one. Now this is really easy to do, we can find the middle index in the entire range of indices of our array of interest and then we can look at one part of the array from the beginning index up to the middle index and the other part of the array from the middle index up to the end index. Once we have divided the array into two sub arrays, we wanted to sort each sub array of size n by 2. Well, how would we do this? Are we going to employ selection sort to do this? Well, I would say let us just wait for a few slides, we will actually see a very elegant way of doing this. But for the time being, let us just assume that we somehow can magically sort these two sub arrays of size n by 2. As we have already seen, just having the two sorted sub arrays does not help us in getting the original sorted array. So we have to merge these two sorted sub arrays each of size n by 2 and now of course the question comes how do we do that? So let us first look at how we might merge two sorted sub arrays each of size n by 2. So here I have two sorted sub arrays each containing three elements, both of them are sorted in decreasing order and what I want to do is I want to merge them and find one sorted array of six elements where the elements are sorted in decreasing order. How might I go about doing that? Well, I could have an index which points to the current maximum element in the two sub arrays and then I could check which of these two elements was larger. In this case, 27 is greater than 24. So therefore, since this is the largest element in this sub array and that is already greater than the largest element in this sub array, so therefore this must be the largest element in the entire array and so I can now put it at the topmost position in the entire sorted array. Once I have done that, I can increment my pointer or my index to point to the next highest element in this sorted sub array while that index stays where it was, we have not yet been able to transfer this number to the sorted array yet. So now I am going to compare these two elements, since 25 is greater than 24 and these elements are already less than or equal to 24 over here, therefore 25 should occupy the next position in the sorted array and this index now comes down and points to 24 and once again I have to compare these two elements, now it turns out that 24 is not really greater than 24, 24 is indeed equal to 24. So now I have a choice of either choosing this or choosing this but let us say for the time being that I am choosing this, so this element now comes down from that array and occupies that next position and of course this index comes down over here. Now I am looking at this part of the sub array, I have already dealt with that element and I know this part is sorted in decreasing order and I am also looking at this final part of the sub array which is also sorted in decreasing order, so I look at the topmost elements which are the maximum elements in these sub arrays that I am looking at and here it is 18, here it is 24, since 24 is greater than 18, the next element to go should be this 24 and then I have now come out of the range of indices of sub array 2 which basically means I have seen the entire sub array 2, so all I now need to do is to take the elements from sub array 1 and just put them in the same sorted order as they appear in sub array 1 in the final sorted array. So this finally gives us the merged sorted array over here and I have seen both these sorted sub arrays, I have examined all their elements and placed them in the rightful place in this merged sorted array. So this is the way in which we could take two sorted sub arrays each of size n by 2 and then merge them into one sorted array of size n, how would we go about sorting each of these sub arrays? This was a problem that we had said we will look at slightly later, so let us now see how would we go about solving this, well if you think about it we were actually trying to sort an array of size n and now this problem says I have to sort two sub arrays each of size n by 2, so why not try the same steps that I was going to use to sort the array of size n to solve each of these sub problems, basically what I am saying is can I recursively sort each of these sub arrays by the same method, well the moment I talk about recursion I have to worry about the termination case and in this case the termination case is easy when I get an array of size 1 that is this exactly one element in the array then of course the array is sorted and I do not need to recurs any further, so this now tells us how we might actually employ a divide and conquer strategy to sort a given array of unsorted integers, so we start with the array of unsorted integers divided into two parts get to similar but simpler problems to solve each of these sub problems I again divided into two parts note that there are three elements, so these two parts would not be of the same size one of them is one element the other has two elements and now if I look at this sub problem it has only one element, so I have hit the termination case the array is already sorted for this sub problem it is again divided into two parts and once again this array has just one element, so it is the termination case this other array also has just one element so it is the termination case, so now I have sorted these two sub arrays in fact sorted them trivially because they had just one element each and now I must merge them back together to get a merged sorted array of two elements, so in this particular case I get this merge sorted array and I already had this merge sorted array from earlier, so now I must merge them together to get this merge sorted array, so that is what I get here and now I must still solve this similar but simpler problem, so once again I will have to divide it into two parts and now this part is an array of size one, so I hit the termination case the array is already sorted for the other part I have to divide it further up into two arrays each of size one but then because this array is of size one I have hit the termination case the other array is also of size one I have hit the termination case, so now I have these two sorted sub arrays I can merge them together to get this merge sorted sub array here is the other merge sorted sub array I can now merge them further to get this merge sorted sub array and finally I have to merge these two sorted sub arrays to finally get the overall sorted and merged array, so finally we have our sorted array and in fact this technique that I just showed by means of an animation to go from this unsorted array to this sorted array is also called merge sort you would have noticed that merging two sorted sub arrays was really the key step in this technique and hence the name merge sort, so in summary in this lecture we looked at the intuition behind a new sorting technique called merge sort in fact merge sort is basically a divide and conquer approach and this naturally leads to a recursive formulation and we also saw the very important role of merging sorted sub arrays when doing merge sort in fact that is the key step in merge sort and that is why the sorting technique is also called merge sort merging is the main step in this process thank you