Now, we'll look at Shellsort which is a bit elementary on the face of it but it's not at all elementary as you'll see. The idea of Shellsort is that Insertion Sort is inefficient because elements really move only one position at the time even when we're kind of know that they have a long way to go. The idea behind Shellsort is that we'll move entries several positions at a time and the way we're going to do it, it's called h-sorting the array. So, an h-sorted array is h different inter leaves sorted sub-sequences so in this case with h=4 if we start at L and look at every fourth element - M, P, T - then it's sorted. If we start in the second place at E and look at every fourth element, it's sorted. So this is 4 interleave sequences, that's a 4-sorted array. And what we're going to do is implement a sorting method that h-sort for decreasing sequences of values of h. This is one of the oldest sorting methods invented by Shell in 1959. So, in this case, it starts out with the input example shown and then the 13-sort - a few items are moved, 4-sort - a few more are moved, and then finally, a 1-sort. And the idea is that each of the sorts can be implemented with only a few exchanges given that the previous ones happened. So first thing is how do we get an array h-sorted? That's actually pretty easy. We just use Insertion Sort but instead of going one back every time we come with a new item, we go h back. So for example when we come to this A in the Insertion Sort, then it's, we look at the array before that and then there was M and E in the positions three back so we exchange the A with the larger one to its left, that's M and then the other larger one to its left, that's E and then put it into position. So the code is the same as insertion, as for Insertion Sort, except that when we go backwards through the array we skip by h instead of just by one. That's how we h-sort an array. And the idea is we're going to use Insertion Sort because of two reasons based on our understanding of how Insertion Sort works. While the first thing is if the increments are big then the size of the sub arrays that we're sorting are pretty small so any sorting method including Insertion Sort is going to work well. But the other thing is if the increments are small because we've done previous h-sorts for bigger values of h, the array is partially sorted and so Insertions Sort is going to be fast. You wouldn't work to use Shellsort as the basis for h-sorting because that always takes quadratic time no matter what order there is in the array. So let's look at example of Shellsort with increment 7, 3, and 1. So, we start with this sort example and then 7-sorting it - just involves doing insertion sort but just reaching back 7 each time. In this case, the 4 subfiles stretched out at seven each only have two elements in them. And then we 3-sort. Now, because it's 7-sorted and a 3-sort elements are either already in placed or on a go back a few strides. On this case, it's only the A that goes back two. And then we 1-sort and again because of the fact that it's been 7-sorted and 3-sorted, the arrays are almost in order when it comes time to do the 1-sort and most of the items only go back one or two positions. So we have to do a few extra passes to do the higher sorts but the each element moves only a little bit on each path and that's how Shellsort gains its efficiency. So actually once you 1-sort, that's Insertion Sort so you're going to always get a sorted result. The only difference is how efficient is that. Now the intuition behind Shellsort and actually the mathematical fact is that if you've got an array that's h-sorted and then you k-sort it for another value k different from h, it's still h-sorted. This is one of those mathematical facts that seems obvious but then if you try to prove that maybe it's a little more subtle than you think. So, if you think of all this is, is, is trivial and easy, go ahead and try to write down a proof that a g-sorted array remains g-sorted even after it's h-sorted. But most people will accept that and it's a fact and that's how Shellsort gains efficiency. Now there's another problem is what increment sequence should we use for Shellsort. One of the first things you might think of is let's try powers of two. Actually that one doesn't work at all, very well at all because it winds up not comparing elements in even positions with elements in the odd positions until the 1-sort which means performance can be bad. Shell's original idea is to try powers to two minus one and that works okay. Knuth when he wrote his books in the 60s proposed the increment sequence 3x + 1. We'll start with the 1, 4, 13, 40, 121, 364 like that and that's good because it's easy to compute. When we're using in Shellsort of course, we find the largest increment less than our file size and then do the sorts for decreasing values of that increment. But finding the best increment sequence is a research problem that has confounded people for quite a long time. Here's an increment sequence that I found after maybe a year's work and it works well but nobody knows if that's the best one. So here's the implementation in Java of Shellsort for Knuth's 3x + 1 increment sequence. We'll just go ahead and compute the increments that are less than n, n / 3 and then starting at that increment whatever it is and say, we started 364 then next time we need an increment, we'll just divide it by 3, 364 integer divide by 3, 364 integer / 3 it gets 121, 40 and so forth. So, this h = h / 3 gets us to the next increment. And then, the implementation is just Insertion Sort. We just go through starting at h for i and when we do the insertion, the j loop, we decrement j by h each time, otherwise the code is exactly like Insertion Sort. So, just adding this extra loop for h-sorting and this extra loop to compute the increments to Insertion Sort, we get a slightly more complicated piece of code but its much, much more efficient. Here's what it looks like for a bigger array. We start with the randomly ordered input and you can see that it gets more and more in order on each time that we h-sort for the decreasing values of h. Here's an animation. This animation does the whole h-sort for each subarray. It's a little better feeling for what's going on. And now to do the high ones pretty quickly and now it's doing the 1-sort and again it steps through the array pretty quickly. If it's partially sorted it doesn't make much difference - does the higher sorts a little bit faster. But that's simple to implement and very efficient sorting algorithm. Now, the analysis of Shellsort is still open. Now, there's a few things that we can say. For example we can say that the number of comparison and the worst case is O(N3/2) for the 3x + 1 increments. But actually in practice it's much less than that. The problem is nobody knows an accurate model for describing the number of compares taken by Shellsort for any interesting increment sequence. This seems to be with a small value, multiple of n times the number of increments used which is some multiple maybe of n log n but nobody is been able to find an accurate model that proves that for any interesting increment sequence for Shellsort. So, why we are interested in this algorithm? Well, it's a simple idea that leads to substantial performance gains. It's very useful in practice because it's pretty fast except for very huge arrays. It's going to beat even the classical sophisticated methods for medium sized arrays. And it doesn't take much code. It's often used in embedded systems or in hardware sort type systems because there's so little code involved to implement it. And it just leads to a lot of interesting questions. This gets to the intellectual challenge of developing algorithms. If you think what we've been studying so far is trivial, go ahead and find a better increment sequence. Try some technique to discover one and try to say something about the average-case performance of Shellsort. People have been trying to do that for 50 years without a whole lot of success. So, the lesson is that we can develop good algorithms or good implementations without much code but there are some out there that are still waiting discovery. It could be that there are some increment sequence out there that make Shellsort more efficient than any other method, any of the sorting method that we know for pratical file size, no one can deny that. That's Shellsort or first non-trivial sorting method.