Lecture 16 | Programming Abstractions (Stanford)
-
0:00 - 0:11
-
0:11 - 0:15This presentation is delivered by the Stanford Center for Professional
-
0:15 - 0:25Development.
-
0:25 - 0:26Okay.
-
0:26 - 0:27So this is
-
0:27 - 0:30the last thing we had talked about at the end of the merge sort was
-
0:30 - 0:35comparing a quadratic and N-squared sort, this left and right sort right here to the linear
-
0:35 - 0:37arrhythmic which is the N-log in
-
0:37 - 0:40kind that merge sort runs in, right, showing you that
-
0:40 - 0:41
-
0:41 - 0:44really way out-performing even on small values and getting the large values
-
0:44 - 0:47[inaudible] just getting enormous in terms of what you can accomplish with
-
0:47 - 0:48a N-log-in algorithm
-
0:48 - 0:50really vastly
-
0:50 - 0:52superior to what you're gonna get out of a N-squared algorithm. I said
-
0:52 - 0:56well, N-log-I told you without proof that you're going to take on faith that I
-
0:56 - 0:57wouldn't lie to you,
-
0:57 - 1:01that that is the best we can do in terms of a comparison based sort,
-
1:01 - 1:04but what we're going to look for is a way of maybe even improving on those
-
1:04 - 1:06kinds of merge sort by kind of a
-
1:06 - 1:09one thing we might want to do is avoid that copying of the data out and back that
-
1:09 - 1:11merge sort does and
-
1:11 - 1:15maybe have some lower cost in factors in the process, right that can bring our
-
1:15 - 1:17times down even better.
-
1:17 - 1:20So the sort we're looking at is quick sort.
-
1:20 - 1:22And I think if you were gonna come up with an algorithm name,
-
1:22 - 1:25naming it Quick Sort becomes good marketing here so it kind of inspires you to
-
1:25 - 1:29believe actually that it's gonna live up to its name, is a divide-and-conquer algorithm
-
1:29 - 1:33that takes a strategy like merge sort in the abstract which is the divide into
-
1:33 - 1:36two pieces and [inaudible] sort those pieces and then join them back
-
1:36 - 1:37together.
-
1:37 - 1:40But whereas merge sort does an easy split hard join,
-
1:40 - 1:43this one flips it on its head and said what if we did some work on the front step
-
1:43 - 1:45in the splitting process
-
1:45 - 1:49and then that may give us less to do on the joining step
-
1:49 - 1:53and so the strategy for quick sort is to run to the pile of
-
1:53 - 1:55papers, whatever we're trying to work at
-
1:55 - 1:57in a partitioning step
-
1:57 - 1:58is the first thing that it does
-
1:58 - 2:01and that's the splitting step and that partitioning is designed to kind of move
-
2:01 - 2:04stuff to the lower half and the upper half.
-
2:04 - 2:07So having some idea of what the middle most value would be,
-
2:07 - 2:11and then actually just walking through the pile of papers and kind of you know,
-
2:11 - 2:13distributing to the left and right
-
2:13 - 2:17portions based on their comparison to this middle-most element.
-
2:17 - 2:21Once I have those two stacks - I've got A through M over here and N through Z over there,
-
2:21 - 2:23that we're cursively sorting those
-
2:23 - 2:26takes place, kind of assuming my delegates do their work
-
2:26 - 2:32and in the process of re-joining them is really kind of simple. They kind of, you know,
-
2:32 - 2:37joined together with actually no extra work, no looking, no process there. So the one
-
2:37 - 2:41thing that actually is is where all the trickiness comes into is this idea of how we
-
2:41 - 2:44do this partitioning.
-
2:44 - 2:47So I was being a little big disingenuous when I said well if I had this stack of exam papers and
-
2:47 - 2:48I know that
-
2:48 - 2:51the names, you know range over the alphabet A through Z then I know where M is and I
-
2:51 - 2:54can say well, that's a good mid pint around to divide.
-
2:54 - 2:57Given that we want to make this work for kind of any sort of data,
-
2:57 - 3:01we're not going to [inaudible] know, what's the minimal most value. If we have a bunch of
-
3:01 - 3:04numbers, are they test scores, in which case maybe 50 is a good place to move.
-
3:04 - 3:06Are they instead, you know,
-
3:06 - 3:09population counts of states in which case millions would be a better
-
3:09 - 3:11number to pick to kind of divide
-
3:11 - 3:12them up. So
-
3:12 - 3:15we have to come up with a strategy that's gonna work, you know, no matter
-
3:15 - 3:19what the input that's somehow gonna pick something that's kind of reasonable
-
3:19 - 3:21for how we're gonna do these divisions. There's
-
3:21 - 3:23this idea of picking, called a pivot.
-
3:23 - 3:28So given this, you know, region, this set of things to sort,
-
3:28 - 3:30how do I know what's a reasonable pivot.
-
3:30 - 3:33We're looking for something that's close to the median is actually ideal.
-
3:33 - 3:34So if we could
-
3:34 - 3:37walk through them and compute the median, that would be the best we could
-
3:37 - 3:38do, we're
-
3:38 - 3:41gonna try to get around to not doing that much work
-
3:41 - 3:45about it, though. We're gonna actually try to kind of make an approximation and we're gonna make a really
-
3:45 - 3:47very simplistic
-
3:47 - 3:50choice about what my approximation would be. We're gonna come back and re-visit
-
3:50 - 3:51this a little bit later.
-
3:51 - 3:56But I want to say, ''Well, I just took the first paper off the stack. If they're in random order,
-
3:56 - 3:58right. I look at the first one; I say Okay, it's,
-
3:58 - 4:00you know, somebody king.
-
4:00 - 4:03Well, everybody less than king goes over here. Everybody greater than king goes over
-
4:03 - 4:07there. Now king may not be perfectly in the middle and we're gonna come back to see
-
4:07 - 4:09what that will do to the analysis,
-
4:09 - 4:12but at least we know it's in the range of the values we're looking at, right, and so it
-
4:12 - 4:14at least did that for us.
-
4:14 - 4:17And it means no matter what our data is, we can always use that. It's a strategy that will always work. Let's
-
4:17 - 4:18just take the thing
-
4:18 - 4:20that we first see
-
4:20 - 4:22and use it to be the pivot and them
-
4:22 - 4:24slot them left and right.
-
4:24 - 4:28So let me go through looking at what the code actually does.
-
4:28 - 4:30This is another of those cases where the
-
4:30 - 4:32code for partition
-
4:32 - 4:35is a little bit
-
4:35 - 4:36frightening
-
4:36 - 4:40and the analysis we're looking at is not actually to get really really worried
-
4:40 - 4:42about the exact details of the less
-
4:42 - 4:45than or the less than or equal to. I'm gonna talk you through what it does,
-
4:45 - 4:48but the more important take-away point is what's the algorithm behind Quick Sort. What's
-
4:48 - 4:53the strategy it's using to divide and conquer and how that's working out.
-
4:53 - 4:56So the main Quick Sort algorithm looks like this. We're given this
-
4:56 - 4:59vector of things we're trying to sort and we have a start index and a stop index
-
4:59 - 5:04that identifies the sub region of the vector that we're currently trying to sort. I'm gonna
-
5:04 - 5:08use this in subsequent calls to kind of identify what piece we're recursively
-
5:08 - 5:09focusing on.
-
5:09 - 5:12As long as there's a
-
5:12 - 5:15positive difference between the start and the stop so there's at least
-
5:15 - 5:16two elements to sort,
-
5:16 - 5:19then we go through the process of doing the division and the sorting. So then
-
5:19 - 5:23it makes the call to partition saying sub-region array
-
5:23 - 5:26do the partition and we'll come back and talk about that code in a second and the thing we're trying to find
-
5:26 - 5:31the partition is the index at which the pivot was placed. So after we did all the
-
5:31 - 5:31work,
-
5:31 - 5:34it moved everything less than the pivot to the left side of that, everything
-
5:34 - 5:36greater than the pivot to the right side
-
5:36 - 5:37and then the pivot will tell us
-
5:37 - 5:41where the division is and then we make two recursive calls
-
5:41 - 5:43to sort everything up to but not including pivot,
-
5:43 - 5:46to sort everything past the pivot to the end,
-
5:46 - 5:49and then those calls are operating on the array in place, so we're not copying it out and
-
5:49 - 5:54copying it back. So in fact, there actually even isn't really any joint step here.
-
5:54 - 5:57We said sort the four things on the left, sort the seven things on the right
-
5:57 - 6:00and then the joining of them was where they're already where they need
-
6:00 - 6:02to be so in fact we don't have anything to do in the
-
6:02 - 6:04joined wall.
-
6:04 - 6:09The tricky part is certainly in partition. The
-
6:09 - 6:12version of the partition we're using here is one that kind of takes two indices,
-
6:12 - 6:14two fingers, you might imagine
-
6:14 - 6:16and it walks a
-
6:16 - 6:18one end from
-
6:18 - 6:22the stop position down and one from the start position over
-
6:22 - 6:26and it's looking for elements that are on the wrong side.
-
6:26 - 6:30So if we start with our right hand finger on the very end of the array,
-
6:30 - 6:31that first loop in there
-
6:31 - 6:35is designed to move the right hand down
-
6:35 - 6:38looking for something that doesn't belong in left side, so we
-
6:38 - 6:41identified 45 as the pivot value. It says
-
6:41 - 6:43find something that's not
-
6:43 - 6:48greater then 45. That's the first thing we found coming in from the right
-
6:48 - 6:50downward that doesn't belong,
-
6:50 - 6:51so only that first step.
-
6:51 - 6:54So it turns out it takes it just one iteration to find that,
-
6:54 - 6:57and so okay, this guy doesn't belong on the right-hand side.
-
6:57 - 7:00Now it does the same thing on the inverse on the left-hand side.
-
7:00 - 7:03Try to find something that doesn't belong on the left-hand side.
-
7:03 - 7:06So the left hand moves up. In
-
7:06 - 7:08this case, it took two iterations to get to that,
-
7:08 - 7:09to this 92.
-
7:09 - 7:13So now we have a perfect opportunity to fix both our problems
-
7:13 - 7:15with one swap,
-
7:15 - 7:16exchange what's
-
7:16 - 7:19at the current position of left hand with right hand and now we will have
-
7:19 - 7:23made both of our problems go away and we'll have kind of more things on the
-
7:23 - 7:24left and the right that belong there
-
7:24 - 7:27and then we can walk inward from there, you know, to find subsequent ones
-
7:27 - 7:29that are out of order.
-
7:29 - 7:31So those two get exchanged and now
-
7:31 - 7:33right again
-
7:33 - 7:35moves into find that 8,
-
7:35 - 7:37left moves over to find that 74.
-
7:37 - 7:38We swap again.
-
7:38 - 7:40And as we just keep doing this,
-
7:40 - 7:41right, until
-
7:41 - 7:43they cross, and once they've cross,
-
7:43 - 7:47right then we know that everything that the right scanned over is greater than the pivot,
-
7:47 - 7:48everything
-
7:48 - 7:51in the left was less than and
-
7:51 - 7:55at that point, right we have divided it, right, everything that's small is kind
-
7:55 - 7:56of in the left side of the
-
7:56 - 7:59vector. Everything that's large in the right side. So I
-
7:59 - 8:03swap these two and now I get to that place and I say okay,
-
8:03 - 8:05so now big things here, small things there.
-
8:05 - 8:10The last thing we do is we move the pivot into the place right between them and
-
8:10 - 8:13know that it is exactly located right in the
-
8:13 - 8:15slot where they cross. Now
-
8:15 - 8:17I have two sub arrays to work on.
-
8:17 - 8:21So the return from partition in this case will be the index four here and it
-
8:21 - 8:24says Okay, go ahead and quick sort
-
8:24 - 8:25this front-most part
-
8:25 - 8:28and then come back and do the second part.
-
8:28 - 8:31So in recursion, kind of think of that as being postponed and it's waiting; we'll get back to it in a minute, but
-
8:31 - 8:34while we work on this step, we'll do this same thing. It's a
-
8:34 - 8:39little big harder to see it in the small kind of what's going on, but in this case, right, it
-
8:39 - 8:44divided that because the pivot was 8 into 8 and the three things greater than the pivot. In
-
8:44 - 8:48this case, the 41 is the pivot so it's actually going to move
-
8:48 - 8:5041 over there. It's going to have the left of that as it keeps
-
8:50 - 8:53working its way down, it gets smaller and smaller and it's harder to see the workings of
-
8:53 - 8:56the algorithm in such a small case of it
-
8:56 - 8:58rearranging it, but
-
8:58 - 8:59we'll get back to the big
-
8:59 - 9:01left half in
-
9:01 - 9:02a second.
-
9:02 - 9:05And so now that that's all been sorted,
-
9:05 - 9:09we're revisiting the side that's advancing above the pivot
-
9:09 - 9:13to get these five guys, six guys in the order, taking the same
-
9:13 - 9:18strategy. You pivot around 67 [inaudible] doing some swapping
-
9:18 - 9:28[inaudible] and
-
9:28 - 9:30
-
9:30 - 9:32we'll see it in slightly bigger case to kind of get the idea,
-
9:32 - 9:35but very quickly there's something very interesting about the way quick sort is working
-
9:35 - 9:38is that that partition step
-
9:38 - 9:41very quickly gets things kind of close to the right place. And
-
9:41 - 9:42so now that we've
-
9:42 - 9:45done both the left and the right
-
9:45 - 9:47we're done. The whole thing is done. Everything kind of got moved into the
-
9:47 - 9:50right position as part of the recursive, part of the sorting and doesn't need to be
-
9:50 - 9:52further moved
-
9:52 - 9:54to solve the whole problem.
-
9:54 - 9:57That first step of the partition is doing a lot of the kind of throwing things kind
-
9:57 - 9:59of left and right,
-
9:59 - 10:03but it's actually quickly moving big things and small things that are out of
-
10:03 - 10:05place closer to where they're gonna eventually need to go, and it turns
-
10:05 - 10:07out to be a real advantage
-
10:07 - 10:11in terms of the running time of this sort because it actually is doing
-
10:11 - 10:14some quick movement close to where it needs to be and that kind of fixes it up in the recursive calls that
-
10:14 - 10:21examine the smaller sub sections of the [inaudible]. Let
-
10:21 - 10:28me show you what it sounds like, because that's really what you want to know. So
-
10:28 - 10:29let's -
-
10:29 - 10:34it's gonna kind of [inaudible]. So
-
10:34 - 10:37you can see the big partitioning happening and
-
10:37 - 10:40then it kind of jumbling things up and then coming back to revisit them, but you
-
10:40 - 10:44notice that quite quickly
-
10:44 - 10:47kind of all the small ones kind of got thrown to the left all. All the large elements to the right
-
10:47 - 10:51and then the kind of process of coming back and so the big partition that you can see kind
-
10:51 - 10:53of working across them and then kind of noodling down.
-
10:53 - 11:21If I turn the sound on for it and I'll probably take it down a little bit.
-
11:21 - 11:25So the big partition steps making a lot of noise, right and moving things kind of
-
11:25 - 11:28quickly and it almost appears, you know, to hear this kind of random sort of it's hard to
-
11:28 - 11:30identify what's going on during the big partition,
-
11:30 - 11:34but then as you hear it make its way down the recursive tree it's
-
11:34 - 11:36focusing on these smaller and smaller regions where the numbers have all been
-
11:36 - 11:39gathered because they are similar in value. And
-
11:39 - 11:42you hear a lot of noodling in the same pitch range
-
11:42 - 11:45region as its working on the smaller and smaller sub arrays and then they definitely go
-
11:45 - 11:49from low to high because of the recursion chooses the left side to operate on
-
11:49 - 11:50before the right side
-
11:50 - 11:51that you hear
-
11:51 - 12:00the work being done in the lower tones before it gets to the finishing up
-
12:00 - 12:01of the high tones. Kinda cool. Let us
-
12:01 - 12:02come back here and talk about
-
12:02 - 12:09how to analyze this guy a little bit.
-
12:09 - 12:09So the main part
-
12:09 - 12:13of the algorithm is very simple and deceptively simple
-
12:13 - 12:15because all the hard work was actually done in partition.
-
12:15 - 12:17The partition step is linear and
-
12:17 - 12:18if you
-
12:18 - 12:21can kind of just go along with me conceptually, you'll see that we're moving this
-
12:21 - 12:24left finger in; we're moving this right finger in
-
12:24 - 12:27and we stop when they cross, so that means every element was looked at.
-
12:27 - 12:28Either
-
12:28 - 12:31they both matched over here and they matched over here, but eventually they let you
-
12:31 - 12:33look at every element as you worked your way in
-
12:33 - 12:37and did some swaps along the way. And so that process is linear and the number of
-
12:37 - 12:39elements. There's a thousand of them kind of has to
-
12:39 - 12:41advance maybe 400 here and 600 there,
-
12:41 - 12:45but we'll look at all the elements and the process of partitioning them to the
-
12:45 - 12:48lower or upper halves.
-
12:48 - 12:50Then it makes two calls, quick sort
-
12:50 - 12:54to the left and the right portions of that.
-
12:54 - 12:56Well, we don't know exactly what that division was,
-
12:56 - 13:00was it even, was it a little lop sided and that's certainly going to come back to be
-
13:00 - 13:01something we're gonna look at.
-
13:01 - 13:05If we assume kind of this is the ideal 50/50 split
-
13:05 - 13:07sort of in an ideal world
-
13:07 - 13:09if that choice we had for the pivot
-
13:09 - 13:13happened to be the median or close enough to the median that effectively we got an even
-
13:13 - 13:15division, at every level of recursion,
-
13:15 - 13:19then the recurrence relation for the whole process is the time required to
-
13:19 - 13:19sort, an
-
13:19 - 13:20input of N
-
13:20 - 13:22is in to partition it
-
13:22 - 13:24and then 2,
-
13:24 - 13:27sorting two halves that are each
-
13:27 - 13:29half again as big as the original input.
-
13:29 - 13:33We saw that recurrence relationship for merge sort; we solved it down.
-
13:33 - 13:37Think in terms of the tree, right you have the branching of three, branching of two, branching of two
-
13:37 - 13:41and at each level the partitioning being done across each level and then it
-
13:41 - 13:47going to a depth of login, right, the number of times you can [inaudible] by two [inaudible]
-
13:47 - 13:49single case arrays that are easily handled.
-
13:49 - 13:53So it is an N login sort in this
-
13:53 - 13:54perfect best
-
13:54 - 13:55case.
-
13:55 - 13:56So that should mean that
-
13:56 - 13:59in terms of Big O growth curves, right,
-
13:59 - 14:02merge sort and quick sort should look about the same.
-
14:02 - 14:05It does have sort of better factors, though.
-
14:05 - 14:06Let me show you.
-
14:06 - 14:08I go back here and I just run them against each other.
-
14:08 - 14:15If I put quick sort versus merge sort here, stop
-
14:15 - 14:17making noise,
-
14:17 - 14:19
-
14:19 - 14:21the quick sort
-
14:21 - 14:22pretty handily
-
14:22 - 14:27managed to beat merge sort in this case, merge sort was on the top, quick sort was underneath
-
14:27 - 14:29and certainly in terms of what was going on it was doing,
-
14:29 - 14:32looks like more comparisons right, to get everything there, that partition
-
14:32 - 14:33step did a lot of comparison,
-
14:33 - 14:35but fewer moves,
-
14:35 - 14:38and that kind of actually does sort of make intuitive sense. You think that quick
-
14:38 - 14:41sort very quickly moves stuff to where it goes and does a little bit of noodling.
-
14:41 - 14:44Merge sort does a lot of moving things away and moving them back and kind of like
-
14:44 - 14:46as you see it growing,
-
14:46 - 14:47you'll see a lot of
-
14:47 - 14:50large elements that get
-
14:50 - 14:53placed up in the front, but then have to be moved again right, because that was
-
14:53 - 14:57not their final resting place. And so merge sort does a lot of kind of movement away and back
-
14:57 - 15:00that tends to cost it overall, right. You know, a
-
15:00 - 15:05higher constant factor of the moves than something like quick sort
-
15:05 - 15:08does where it more quickly gets to the right place and then doesn't move it
-
15:08 - 15:13again. So
-
15:13 - 15:16that was all well and good. That was assuming that everything went perfectly.
-
15:16 - 15:20That was given our simplistic choice of the pivot,
-
15:20 - 15:24you can imagine that's really assuming a lot right that went our way.
-
15:24 - 15:29If we look at a particularly bad split,
-
15:29 - 15:32let's imagine that the number we have to pick is pretty close to,
-
15:32 - 15:34you know, one of the extremes. If I were
-
15:34 - 15:35sorting papers by alphabet
-
15:35 - 15:38and if the one on top happened to be a C,
-
15:38 - 15:40right, well then I'm gonna be dividing it pretty lop sided, right, it's just gonna
-
15:40 - 15:44be the As and the Bs on one side and then everything [inaudible] to the end on the other
-
15:44 - 15:45side.
-
15:45 - 15:49If I got a split that was about 90/10, ninety percent went on one side, ten
-
15:49 - 15:50percent on the other,
-
15:50 - 15:52you would expect right
-
15:52 - 15:56for it to kind of change the running time of what's going on here, so I get
-
15:56 - 15:59one tenth of them over here and the low half and maybe be nine-tenths in the right half.
-
15:59 - 16:03Let's just say every time it always takes nine-tenths and moves it to the upper half, so I
-
16:03 - 16:05kept picking something that's artificially close to the front.
-
16:05 - 16:07These like will kind of peter out
-
16:07 - 16:11fairly quickly diving N by 10 and 10 and 10 and 10, eventually these are gonna peter
-
16:11 - 16:14out very soon, but this one arm over there
-
16:14 - 16:18where I keep taking 90 percent of what remains. I had 90 percent, but I had
-
16:18 - 16:1981 percent.
-
16:19 - 16:23I keep multiplying by nine-tenths and I'm still kind of retaining a lot of
-
16:23 - 16:26elements on this one big portion,
-
16:26 - 16:29that the depth of this tree isn't gonna bottom out quite as quickly as it
-
16:29 - 16:33used to, but it used to the number of times you could divide N by 2, the log based
-
16:33 - 16:352 of N was where we landed.
-
16:35 - 16:37In this case, I have to
-
16:37 - 16:40take N and multiply it by nine-tenths so
-
16:40 - 16:41instead of one half,
-
16:41 - 16:43right, to the K, it's nine tenths to the K
-
16:43 - 16:47and it's like how many iterations how deep will this get before it gets
-
16:47 - 16:49to the simple case
-
16:49 - 16:51and so solving for
-
16:51 - 16:56N equals ten-ninths to the K is taking the log-based ten-ninths of both sides,
-
16:56 - 17:02then K, the number of levels is the log-based ten-ninths of them. We're kind of
-
17:02 - 17:05relying on a fact of mathematics here though is that all algorithms are the
-
17:05 - 17:09same value, so log-based A of N and log-based B of
-
17:09 - 17:12N, they only differ by some constant that you can
-
17:12 - 17:15compute if you just rearrange the terms around. So in effect
-
17:15 - 17:16this means that
-
17:16 - 17:20there is a constant in front of this. It's like a constant
-
17:20 - 17:23difference, the ratio between ten-ninths and 2
-
17:23 - 17:27that distinguishes these, but it still can be logged based 2 of N in
-
17:27 - 17:30terms of Big O, right, where we can throw away those constants.
-
17:30 - 17:34So even those this will perform, obviously in, you know,
-
17:34 - 17:38experimentally you would expect that getting this kind of split would cause it
-
17:38 - 17:39to
-
17:39 - 17:40work more slowly than it would have
-
17:40 - 17:44in a perfect split situation. The Big O [inaudible] is still gonna look in-log-in arrhythmic and
-
17:44 - 17:47[inaudible]. So
-
17:47 - 17:50that was pretty good to know. So it makes you feel a little bit confident, like sometimes it might be
-
17:50 - 17:54getting an even split and sometimes it might be getting one-third, two-thirds, sometimes it might be getting
-
17:54 - 17:56you know, nine-tenths, but if it was kind of
-
17:56 - 18:01in the mix still dividing off some fraction is still doing okay.
-
18:01 - 18:07Now, let's look at the really, really, really worst case split. The
-
18:07 - 18:10really, really worst case split right, it didn't even take off
-
18:10 - 18:13a fraction. It just managed to separate one,
-
18:13 - 18:15but somehow the pivot here
-
18:15 - 18:16
-
18:16 - 18:17did a really
-
18:17 - 18:20terribly crummy job, right, of dividing it at all
-
18:20 - 18:23that in effect, all the elements were greater than the pivot or less than
-
18:23 - 18:27the pivot since they all landed on one side and the pivot was kind of by itself.
-
18:27 - 18:29So starting with an input of size N,
-
18:29 - 18:33we sectioned off 1 and we had N minus 1 remaining. Well, the next time,
-
18:33 - 18:36we sectioned off another one, so this happened again and again and again.
-
18:36 - 18:39We just got really bad luck all the way through.
-
18:39 - 18:42Each of these levels is only making progress for the base case at a snails
-
18:42 - 18:43pace.
-
18:43 - 18:47Right, one element is being subtracted each subsequent level
-
18:47 - 18:50and that's gonna go to a depth of N.
-
18:50 - 18:53And so now if we're doing N work across the levels, it isn't quite N
-
18:53 - 18:56work because in fact, some of these bottom out. It's still the Gaussian sum in the
-
18:56 - 18:57end
-
18:57 - 19:01is that we are got N levels doing N work each.
-
19:01 - 19:03We suddenly have
-
19:03 - 19:05what was a linear arrhythmic algorithm
-
19:05 - 19:07now performing quadritically. So
-
19:07 - 19:09in the class the selection sort,
-
19:09 - 19:11inscription sort
-
19:11 - 19:14in its worst-case behavior.
-
19:14 - 19:17So quite a range whereas merge sort is a very reliable performer, merge doesn't
-
19:17 - 19:18care.
-
19:18 - 19:21No matter what the order is, no matter what's going on, it's the same
-
19:21 - 19:22amount of work,
-
19:22 - 19:26it means that there's some inputs that can cause quick sort to vary between being linear
-
19:26 - 19:27arrhythmic or being quadratic,
-
19:27 - 19:30and there's a huge difference as we saw in our earlier charts about
-
19:30 - 19:32how those things will run for
-
19:32 - 19:36large values. So what
-
19:36 - 19:38makes the worst case
-
19:38 - 19:42- given how we're choosing a pivot right now is to take the first thing in the
-
19:42 - 19:44sub section to look at as the pivot,
-
19:44 - 19:47what's the example input that gives you this? Sorted. If
-
19:47 - 19:49it's already sorted.
-
19:49 - 19:50Isn't that a charmer?
-
19:50 - 19:54Here's a sorting algorithm. If you ask it to do something
-
19:54 - 19:56and in fact if you accidentally [inaudible] twice, you already had sorted
-
19:56 - 19:59the data and you said, ''Oh, you did something,'' and you passed it back to the sort,
-
19:59 - 20:03it would suddenly actually degenerate into its very worst case. It's already
-
20:03 - 20:05sorted, so it would say,
-
20:05 - 20:06''I've got this stack of exam papers.''
-
20:06 - 20:09I look at the first one and I say, ''Oh, look it's Adam's.'' And I say, ''Okay, well, let me
-
20:09 - 20:12go find all the ones that belong in the left side.'' None of them do. I said, ''Okay,
-
20:12 - 20:15well put Adam's over here.'' I'll [inaudible] sort that. That was easy.
-
20:15 - 20:18Oh, let me look at what I've got left, oh with baker on the top.
-
20:18 - 20:21Okay, well let me put Baker by itself, but could we find the other ones? Oh, no,
-
20:21 - 20:24no more. It would just you
-
20:24 - 20:27know, continue because I'm doing this thing, looking at all N, looking at all N minus 1, looking
-
20:27 - 20:31at N minus 2, all the way down to the bottom making no,
-
20:31 - 20:35recognizing nothing about how beautifully the data already was arranged
-
20:35 - 20:36and
-
20:36 - 20:38you know, getting its worst case.
-
20:38 - 20:42There's actually a couple of others that come in, too. That's probably the most obvious one to think
-
20:42 - 20:46of is it's coming in in increasing order. It's also true if its in decreasing order.
-
20:46 - 20:49If I happen to have the largest value on the top, then
-
20:49 - 20:52I'll end up splitting it all into, everything to the left side and nothing
-
20:52 - 20:53to the right.
-
20:53 - 20:58There are actually other variations that will also produce this. If at any given
-
20:58 - 21:01stage that we're looking at a sub array, if the first value happens to be the extreme
-
21:01 - 21:04of what remains whether it's the small to the large, and it could alternate, which would
-
21:04 - 21:06be kind of a funny pattern, but if you
-
21:06 - 21:10have the tallest and the shortest and the tallest and then another tallest and then a shortest,
-
21:10 - 21:13so those would look a little bit harder to describe, but
-
21:13 - 21:18there are some other alternatives, that product this bad result.
-
21:18 - 21:21All of these we could call degenerate cases.
-
21:21 - 21:25There's a small number of these relative to the N factorial [inaudible] your
-
21:25 - 21:28data could come in. In fact, there was a huge number, and so there's lots and
-
21:28 - 21:29lots of ways it could be arranged.
-
21:29 - 21:32There's a very small number of them that would be arranged in such a way to
-
21:32 - 21:35trigger this very, very worst-case behaviors.
-
21:35 - 21:38Some are close to worst case, like if they were almost sorted, they might every now and
-
21:38 - 21:41then get a good split, but mostly a bad split,
-
21:41 - 21:44but the number that actually degenerate to the absolute worst case is actually
-
21:44 - 21:47quite small, but
-
21:47 - 21:49the truth is
-
21:49 - 21:51is do we expect that those outputs are somehow
-
21:51 - 21:56hard to imagine us getting. Are they so unusual
-
21:56 - 21:59and weird that you might be willing to say it's okay that my algorithm has
-
21:59 - 22:01this one or a couple of bad cases in it
-
22:01 - 22:03because it never comes up.
-
22:03 - 22:06In this case, the only thing that your data came in sorted or almost sorted or reverse sorted
-
22:06 - 22:09is probably not unlikely.
-
22:09 - 22:11It might be that you know, you happen to be reading from
-
22:11 - 22:15a file on disc and somebody has taken the [inaudible] and sort it before they gave the
-
22:15 - 22:19data to you. If all the sudden that caused your program to behave really badly,
-
22:19 - 22:20that would really be
-
22:20 - 22:21a
-
22:21 - 22:23pretty questionable outcome.
-
22:23 - 22:27So let's go aback and look at just to see, though. It's kind of interesting to see
-
22:27 - 22:30it happening in
-
22:30 - 22:33- this is against quick sort versus merge sort.
-
22:33 - 22:38If I change the data to be partially sorted
-
22:38 - 22:41and let it run again,
-
22:41 - 22:43if I still manage to beat it
-
22:43 - 22:44doing a little bit more,
-
22:44 - 22:47if I change it to totally sorted
-
22:47 - 22:53or reverse sorted, for that matter, and
-
22:53 - 22:54so they look like they're doing a lot of work,
-
22:54 - 22:56a lot of work about nothing.
-
22:56 - 22:57And you can see that quick sort
-
22:57 - 22:59really is still way back there.
-
22:59 - 23:02It has looked at the first 10 percent or so and is doing a lot
-
23:02 - 23:04of frantic partitioning
-
23:04 - 23:07that never moves anything.
-
23:07 - 23:11And visibly kind of traipsing it's way up there. Merge sort meanwhile is actually
-
23:11 - 23:13on the beach in Jamaica with a
-
23:13 - 23:15daiquiri
-
23:15 - 23:16mocking quick sort
-
23:16 - 23:21for all those times that it had said it was so much better than it was.
-
23:21 - 23:24''Duh, it was already sorted; you Doofus.''
-
23:24 - 23:25Apparently it wasn't listening. Merge
-
23:25 - 23:28sort almost looked like it did nothing and that's because it took the left half,
-
23:28 - 23:32which is the smallest half, moved it off, right, kind of copied it back and it ends up copying
-
23:32 - 23:38each element back to the same location it was already originally present in. There you go, quick sort
-
23:38 - 23:39taking its time and it if I
-
23:39 - 23:42ran it against, let's say,
-
23:42 - 23:46insertion sort and selection sort, why not
-
23:46 - 23:50[inaudible] nothing better to do than to sort for you all day long.
-
23:50 - 23:54So there insertion sort actually finishing very early because it does nothing. It sort of
-
23:54 - 23:57looked at them all and said they were already in the right order,
-
23:57 - 24:00merge sort doing a little bit more work to move everything back and forth in the same place.
-
24:00 - 24:02But
-
24:02 - 24:02
-
24:02 - 24:04in this case, selection sort
-
24:04 - 24:06and
-
24:06 - 24:08quick sort here at the bottom and selection sort here at the top
-
24:08 - 24:11doing really roughly about the same work if you look at the sum total of the comparisons
-
24:11 - 24:13and moves
-
24:13 - 24:16and then time spent on those suddenly shows that yeah, in this input
-
24:16 - 24:19situation quick sort is performing like an N-squared sort,
-
24:19 - 24:23and obviously very similar constant factors to those present in selection sort,
-
24:23 - 24:24so really
-
24:24 - 24:28behaving totally quadratically in that worst-case input. If I make
-
24:28 - 24:38it reverse sorted, it's a little more interesting because you can kind of see something going on. Everybody kind of doing their thing.
-
24:38 - 24:40Insertion sort now kind of hitting its worst case,
-
24:40 - 24:43so it actually coming in dead last because it
-
24:43 - 24:45did so much extra moving, but
-
24:45 - 24:49still showing the kind of quadratic terms, right, that selection
-
24:49 - 24:53sort and quick sort are both having, but higher constant factors there, so taking almost
-
24:53 - 24:54twice as long because
-
24:54 - 24:55actually doing a little
-
24:55 - 25:02bit extra work because of that inverted
-
25:02 - 25:04situation. [Inaudible] something big, just cause. We'll put it back
-
25:04 - 25:10into random, back into full speed and kind of watch some things happen.
-
25:10 - 25:11So quick sort right, just
-
25:11 - 25:14sort of done in a flash, merge sort finishing behind it
-
25:14 - 25:17and ordinarily
-
25:17 - 25:20the quadratic sorts taking quite a much
-
25:20 - 25:22longer time than our two recursive sorts. But
-
25:22 - 25:30it's the random input really buying quick sort its speed. Is
-
25:30 - 25:33it gonna win - oh, come on. Oh, come on. Don't you want selection sort to come behind? I always wanted it to
-
25:33 - 25:37come from behind. It's kind of like rooting for the underdog.
-
25:37 - 25:38Yes.
-
25:38 - 25:42And yet, just remember don't mock insertion sort. What it sorted is
-
25:42 - 25:46the only one that recognizes it and does something clever about it. [Inaudible]
-
25:46 - 25:49sort is anti-clever about it, so
-
25:49 - 25:55it still can hold its head up and be proud. This
-
25:55 - 25:58kind of [inaudible]. I was
-
25:58 - 26:01thinking about like what algorithms, right, there's a reason why
-
26:01 - 26:04there's four that we talked about and there's actually a dozen
-
26:04 - 26:07more. It's like different situations actually produce different
-
26:07 - 26:09outcomes for different
-
26:09 - 26:12sorts and there are reasons that even though they might not be the best sort for all
-
26:12 - 26:15purposes, there are some situations where it might be the right one, so if you had it,
-
26:15 - 26:18as data said that you expect it to be mostly sorted,
-
26:18 - 26:19but had a few [inaudible] in it.
-
26:19 - 26:22Like if you had a pile or sand papers that were sorted and you dropped them on the floor and they
-
26:22 - 26:25got scuffed up a little bit, but they're still largely sorted, insertion sort is the
-
26:25 - 26:26way to
-
26:26 - 26:29go. It will take advantage of the work that was already done
-
26:29 - 26:33and not redo it or create kind of havoc the way quick sort
-
26:33 - 26:36would. But quick sort, the last thing we need to tell you, though, about it is we can't
-
26:36 - 26:40tolerate this. Like the way quick sort is in its classic form
-
26:40 - 26:41with this
-
26:41 - 26:42first element as pivot
-
26:42 - 26:45would be an unacceptable way to do this algorithm.
-
26:45 - 26:49So quick sort actually typically is one of the most standard element that's offered in
-
26:49 - 26:52a library of programming languages, the sort element.
-
26:52 - 26:53Well, it
-
26:53 - 26:57has to have some strategy for how to deal with this in a way that does not
-
26:57 - 26:59degenerate
-
26:59 - 27:02and so the idea is, what you need to do is just pick a different
-
27:02 - 27:03choice for the pivot,
-
27:03 - 27:06a little bit more clever, spend a little bit more time,
-
27:06 - 27:09do something that's a little less predictable than just picking that first
-
27:09 - 27:11most element.
-
27:11 - 27:12So to take
-
27:12 - 27:16it to the far extreme, one thing you could do is just computer the median, analyze the data and compute the median.
-
27:16 - 27:19It turns out there is a linear time algorithm for this that
-
27:19 - 27:22would look at every element of the data set once and then be able to tell
-
27:22 - 27:23you what the median was
-
27:23 - 27:25and that would guarantee you that 50/50 split.
-
27:25 - 27:30So if you go find it and use it at every stage, you will guarantee it.
-
27:30 - 27:34Most algorithms don't tend to do that. That's actually kind of overkill for the problem. We
-
27:34 - 27:34want to get it to where
-
27:34 - 27:38it's pretty much guaranteed to never get the worst case. But we're not
-
27:38 - 27:41concerned with it getting 50/50. It's got 60/40 or something close enough, that
-
27:41 - 27:45actually, you know, 60/40, 70/30 and it was
-
27:45 - 27:47bopping around in that range it'd be fine,
-
27:47 - 27:50so the other two that are much more commonly used
-
27:50 - 27:53is some kind of approximation of the median
-
27:53 - 27:56with a little bit of guessing or something in it. For example, median of three
-
27:56 - 27:57takes
-
27:57 - 28:01three elements and typically it takes three from some specified position, it takes
-
28:01 - 28:02the middle most element,
-
28:02 - 28:04the last element and the front element and it says,
-
28:04 - 28:06''Okay, given those three,
-
28:06 - 28:10we arrange them to find out what's the middle of those three, and use that.''
-
28:10 - 28:12If the data was already sorted, it turns out you've got the median, right
-
28:12 - 28:14because it wasn't the middle most.
-
28:14 - 28:17If data was just in random position, then you've got one that you know, at least
-
28:17 - 28:22there's one element on one side, right, and so the odds that that every single time
-
28:22 - 28:25would produce a very bad split is pretty low.
-
28:25 - 28:28There are some inputs that could kind of get it to generate a little bit, but it's
-
28:28 - 28:32pretty foolproof in most ordinary situations.
-
28:32 - 28:36Even more unpredictable would be just choose a random element.
-
28:36 - 28:39So look at the start to stop index you have, pick an random there,
-
28:39 - 28:44flop in to the front and now use it as the pivot element.
-
28:44 - 28:45If you
-
28:45 - 28:47don't know ahead of time how your random number [inaudible] it's impossible
-
28:47 - 28:51to generate an input and force it into the worst-case behavior. And so the idea is that
-
28:51 - 28:53you're kind of counting on randomness
-
28:53 - 28:56and just the probabilistic outcome if
-
28:56 - 29:00it managing to be such that the way it shows the random element was to pick the
-
29:00 - 29:02extreme and everything, it is just impossible,
-
29:02 - 29:04the odds are astronomically against it,
-
29:04 - 29:06and so it will,
-
29:06 - 29:08a very simple fix, right
-
29:08 - 29:09
-
29:09 - 29:12that still leaves the possibility of the worst case in there,
-
29:12 - 29:17but you know, much, much, much far removed probability sense. So,
-
29:17 - 29:20just simple things, right, but from there the algorithm operates the
-
29:20 - 29:22same way it always has which is to say,
-
29:22 - 29:24''Pick the median, however, you want to do it,
-
29:24 - 29:27move it into that front slot and then carry on as before in terms of the left
-
29:27 - 29:30and the right hand and moving down and swapping and recursing and all that [inaudible].''
-
29:30 - 29:34Any
-
29:34 - 29:40questions; anything about sorting, sorting algorithms? Why don't we
-
29:40 - 29:42do some coding actually,
-
29:42 - 29:44which is the next thing I want to show you
-
29:44 - 29:46because once you know how to write sorts,
-
29:46 - 29:47
-
29:47 - 29:50sort of the other piece I think you need to have to go with it is how would I write
-
29:50 - 29:54a sort to be generally useful in a large variety of situations that
-
29:54 - 29:57knowing about these sorts I might decide to build
-
29:57 - 30:01myself a really general purpose, good, high performance, quick sort, but I
-
30:01 - 30:03could use again, and again and again.
-
30:03 - 30:07I want to make it work generically so I could sort strings, I could sort
-
30:07 - 30:10numbers, or I could sort students, or I could sort
-
30:10 - 30:11vectors of students or whatever,
-
30:11 - 30:14and I'd want to make sure that no matter what I needed to do it was gonna
-
30:14 - 30:17solve all my problems, this one kid of sorting tool,
-
30:17 - 30:20and we need to know a little bit of C++ to make that work
-
30:20 - 30:22by use of the function template.
-
30:22 - 30:27So if you want to ask about sorting algorithms, now is the time. [Inaudible]. We don't
-
30:27 - 30:28bubble sort,
-
30:28 - 30:31which is kind of interesting. It will come up actually in the assignment
-
30:31 - 30:34I give you next week because it is a little bit of an historical artifact
-
30:34 - 30:38to know about it, but it turns out bubble sort is one of those sorts that
-
30:38 - 30:43is dominated by pretty much every other sort you'll know about in every way, as there's
-
30:43 - 30:45really nothing to recommend it. As I said, each of these four have something
-
30:45 - 30:49about them that actually has a strength or whatever. Bubble sort really doesn't.
-
30:49 - 30:52It's a little bit harder to write than insertion sort. It's a little bit slower than insertion
-
30:52 - 30:56sort; it's a little bit easier to get it wrong than insertion sort. It has higher constant
-
30:56 - 30:57factors. You know,
-
30:57 - 31:01it does recognize the data and sort order, but so does insertion sort, so it's hard to come up with
-
31:01 - 31:04a reason to actually spend a lot of time on it, but I will expose you to it in the
-
31:04 - 31:07assignment because I think it's a little bit of a -
-
31:07 - 31:08it's part of
-
31:08 - 31:10our history right, as a computer science
-
31:10 - 31:14student to be expose to.
-
31:14 - 31:16Anything else? I'm gonna show
-
31:16 - 31:19you some things about function templates. Oh, these
-
31:19 - 31:21are some numbers; I forgot to give that.
-
31:21 - 31:23Just to say, in the end, right,
-
31:23 - 31:26which we saw a little bit in the analysis that the constant factors on quick
-
31:26 - 31:29sort are
-
31:29 - 31:33noticeable when compared to merge sort by a factor of 4,
-
31:33 - 31:35moving things more quickly and not having to
-
31:35 - 31:39mess with them again. Quick
-
31:39 - 31:41sort [inaudible]
-
31:41 - 31:44in totally random order?
-
31:44 - 31:48Yes, they are. Yes - So it doesn't have them taking - So this is actually using a classic quick
-
31:48 - 31:52sort with no degenerate protection on random data.
-
31:52 - 31:55If I had put it in, sorted it in on that case, you would definitely see
-
31:55 - 31:58like numbers comparable to like selection sorts, eight hours in that
-
31:58 - 32:00last slot, right. Or
-
32:00 - 32:01you
-
32:01 - 32:03[inaudible] degenerate protection, and it would probably
-
32:03 - 32:07have an in the noise a small slow down for that little extra work that's being
-
32:07 - 32:11done, but then you'll be getting in log and performance reliable across
-
32:11 - 32:13all states of inputs. So
-
32:13 - 32:15[inaudible] protection as it
-
32:15 - 32:19starts to even out time wise with merge sort, does it still - No, it doesn't.
-
32:19 - 32:23It actually is an almost imperceptible change in the time because it depends on
-
32:23 - 32:26which form of it you use because if you use, for example the random or median of three,
-
32:26 - 32:31the amount of work you're doing is about two more things per level in the tree and
-
32:31 - 32:34so it turns out that, yeah,
-
32:34 - 32:37over the space of login it's just not enough to even be noticeable.
-
32:37 - 32:41Now if you did the full median algorithm, you could actually start to see it because then
-
32:41 - 32:45you'd see both a linear partition step and a linear median step and that
-
32:45 - 32:47would actually raise the cause and factors where it would probably be closer in line to
-
32:47 - 32:49merge sort. Pretty
-
32:49 - 32:58much nobody writes it that way is the truth, but you could kind of in theory is why we [inaudible]. What I'm
-
32:58 - 32:59going to show you, kind
-
32:59 - 33:02of motivate this by starting with something simple, and then we're gonna move towards kind of building
-
33:02 - 33:04the
-
33:04 - 33:05fully generic,
-
33:05 - 33:06
-
33:06 - 33:08you know, one
-
33:08 - 33:10algorithm does it all,
-
33:10 - 33:12sorting function.
-
33:12 - 33:16So what I'm gonna first look at is flop because it's a little bit easier to see it in this case,
-
33:16 - 33:19is that you know, sometimes you need to take two variables and exchange their values. I mean
-
33:19 - 33:23you need to go through a temporary to copy one and then copy the other back and what
-
33:23 - 33:26not - swapping characters, swapping ends, swapping strings, swapping students, you
-
33:26 - 33:28know, any kind of variables you wanted to swap,
-
33:28 - 33:29you could write
-
33:29 - 33:31a specific swap function
-
33:31 - 33:35that takes two variables by reference of the integer, strain or character type that
-
33:35 - 33:36you're trying to exchange
-
33:36 - 33:40and then copies one to a temporary and exchanges the two values.
-
33:40 - 33:43Because of the way C++ functions work, right,
-
33:43 - 33:46you really do need to say, ''It's a string, this is a string, you know, what's being
-
33:46 - 33:49declared here is a string,'' and so you might say, ''Well, if I need more than one swap, sometimes that swaps strings and characters, you know, my choices
-
33:49 - 33:52are
-
33:52 - 33:53basically
-
33:53 - 33:58to duplicate and copy and paste and so on.
-
33:58 - 34:02That's not good; we'd rather not do that.
-
34:02 - 34:04But what I want to do is I want to
-
34:04 - 34:08discuss what it takes to write something in template form.
-
34:08 - 34:12We have been using templates right, the vector is a template, the set is a
-
34:12 - 34:15template, the stack and queue and all these things are templates
-
34:15 - 34:17that are written
-
34:17 - 34:20in a very generic way using a place
-
34:20 - 34:24holder, so the code that holds onto your collection of things is written
-
34:24 - 34:27saying, ''I don't know what the thing is; is it a string; is it an N; is it a car?'' Well,
-
34:27 - 34:31vectors just hold onto things and you as a client can decide what you're gonna
-
34:31 - 34:33be storing in this particular kind of vector.
-
34:33 - 34:37And so what we're gonna see is if I take those flat functions and I try to
-
34:37 - 34:41distill them down and say, ''Well, what is it that any swap routine looks like?''
-
34:41 - 34:43It needs to take two variables by reference, it needs
-
34:43 - 34:46to declare a template of that type and it needs to do the assignment all around
-
34:46 - 34:47
-
34:47 - 34:49to exchange those values.
-
34:49 - 34:51Can I write a version
-
34:51 - 34:55that is tight unspecified leaving a placeholder in there for
-
34:55 - 34:59what -
-
34:59 - 35:00that's really
-
35:00 - 35:01kind of amazing,
-
35:01 - 35:03that what we'Q1: gonna be swapping
-
35:03 - 35:05and then
-
35:05 - 35:10let there be multiple swaps generated from that one pattern.
-
35:10 - 35:11So we're gonna do this actually in
-
35:11 - 35:14the compiler because it's always
-
35:14 - 35:16nice to see a little bit a code happening. So I
-
35:16 - 35:19go over here
-
35:19 - 35:20and
-
35:20 - 35:24I got some code up there that
-
35:24 - 35:26I'm just currently gonna [inaudible] because I don't want to deal
-
35:26 - 35:30with it right now. We're gonna see it in a second. It doesn't [inaudible]. Okay,
-
35:30 - 35:41so your usual swap looks like this.
-
35:41 - 35:44And that would only swap exactly integers. If I wanted characters I'd
-
35:44 - 35:49change it all around. So what I'm gonna change it to is a template. I'm gonna add a template
-
35:49 - 35:50header at the top
-
35:50 - 35:53and so the template header starts with a key-word template and then angle brackets that
-
35:53 - 35:54says,
-
35:54 - 35:59''What kind of placeholders does this template depend on?'' It depends on one type name
-
35:59 - 36:00and then I've chose then name
-
36:00 - 36:02capital T, type for it.
-
36:02 - 36:04That's a choice that I'm going to make and it says
-
36:04 - 36:07in the body of the function that's coming up
-
36:07 - 36:08where I would have
-
36:08 - 36:11ordinarily fully committed on the type, I'm gonna use this placeholder
-
36:11 - 36:13capital T, type
-
36:13 - 36:22instead.
-
36:22 - 36:25And now I have written swap in such a way that it doesn't say for sure
-
36:25 - 36:29what's being exchanged, two strings, two Ns, two doubles. They're all
-
36:29 - 36:33have to be matching in this form, and I said, ''Well, there's a placeholder, and the placeholder
-
36:33 - 36:36was gonna be filled in by the client who used this flop,
-
36:36 - 36:41and on demand, we can instantiate as many versions of the swap function as we need.''
-
36:41 - 36:45If you need to swap integers, you can instantiate a swap that then fills in the
-
36:45 - 36:48placeholder type with Ns all the way through
-
36:48 - 36:51and then I can use that same template or pattern to generate one that will swap
-
36:51 - 36:53characters or swap strings or swap whatever.
-
36:53 - 37:02So if I go down to my main, maybe I'll just pull my main up [inaudible]. And
-
37:02 - 37:05I will show you how I can do this. I can say
-
37:05 - 37:08int 1 equals
-
37:08 - 37:1354, 2 equals 32 and I say swap 1-2.
-
37:13 - 37:17So if the usage of a function is a little bit different
-
37:17 - 37:19than it was for
-
37:19 - 37:21class templates,
-
37:21 - 37:25in class templates we always did this thing where I said
-
37:25 - 37:29the name of the template and then it angled back, as I said. And in particular I want
-
37:29 - 37:33the swap function that operates where the template parameter has been filled in
-
37:33 - 37:35with int
-
37:35 - 37:38that in the case of functions, it turns out it's a little bit easier for the compiler
-
37:38 - 37:39to know what you intended
-
37:39 - 37:42that on the basis of what my arguments are to this,
-
37:42 - 37:45is I called swap passing two integers,
-
37:45 - 37:49it knows that there's only one possibility for what version of swap you were interested
-
37:49 - 37:50in,
-
37:50 - 37:54that it must be the one where type has been filled in with int and that's
-
37:54 - 37:56the one to generate for you.
-
37:56 - 37:59So you can use that long form of saying swap, angle bracket int,
-
37:59 - 38:03but typically you will not; you will let the compiler infer it for you on the usage,
-
38:03 - 38:05so based on the arguments you passed,
-
38:05 - 38:10it will figure out how to kind of match them to what swap said it was taking and
-
38:10 - 38:13if it can't match them, for example, if you pass one double and one int, you'll get compiler
-
38:13 - 38:14errors.
-
38:14 - 38:19But if I've done it correctly, then it will generate for me a swap
-
38:19 - 38:23where type's been filled in with int and if I call it again,
-
38:23 - 38:26passing different kinds of things, so having
-
38:26 - 38:29string S equals hello and T
-
38:29 - 38:31equals
-
38:31 - 38:33world,
-
38:33 - 38:37that I can write swap S and T and now
-
38:37 - 38:40the compiler generated for me two different versions of swap, right,
-
38:40 - 38:43one for integers, one for
-
38:43 - 38:46strings on the [inaudible] and I didn't do anything with them. I put them [inaudible], so nothing to see there,
-
38:46 - 38:47but showing
-
38:47 - 38:50it does compile and build up. That's
-
38:50 - 38:53a pretty neat idea.
-
38:53 - 38:55Kind of important because it turns out there are
-
38:55 - 38:59a lot of pieces of code that you're gonna find yourself wanting to write that don't
-
38:59 - 39:02depend, in a case like swap, swap doesn't care what it's exchanging, that they're Ns, that
-
39:02 - 39:06they're strings, that they're doubles. The way you swap two things
-
39:06 - 39:09is the same no matter what they are. You copy one aside; you overwrite one;
-
39:09 - 39:11you overwrite the other
-
39:11 - 39:14and the same thing applies to much more algorithmically interesting problems
-
39:14 - 39:15like
-
39:15 - 39:19searching, like sorting, like removing duplicates, like printing,
-
39:19 - 39:23where you want to take a vector and print all of its contents right that
-
39:23 - 39:24the
-
39:24 - 39:27steps you need to do to print a vector of events looks just like the steps you need to do to print a vector
-
39:27 - 39:31of strings. And so it would be very annoying every time I need to do that to
-
39:31 - 39:33duplicate that code that there's a real appeal toward
-
39:33 - 39:35writing it once, as a template
-
39:35 - 39:37and using it
-
39:37 - 39:41in multiple situations. So
-
39:41 - 39:44this shows that if I swap, right,
-
39:44 - 39:47it infers what I meant
-
39:47 - 39:50and then this thing basically just shows what happened is when I said
-
39:50 - 39:53int equals four,
-
39:53 - 39:56[inaudible] use that pattern to generate the swap int
-
39:56 - 39:59where the type parameter, that placeholder has been
-
39:59 - 40:01filled in
-
40:01 - 40:05and established that it's int for this particular version which is distinct from
-
40:05 - 40:10the swap for characters and swap for strings and what not. So
-
40:10 - 40:13let me show you that version I talked about print, and this one I'm
-
40:13 - 40:15gonna go back to the
-
40:15 - 40:16compiler for just a second.
-
40:16 - 40:19Let's say I want to print a vector, printing a vector it like iterating all
-
40:19 - 40:22the members and using the
-
40:22 - 40:23screen insertion to print them out
-
40:23 - 40:26and so here it is taking some vector
-
40:26 - 40:29where the elements in it are of this type name. In this case, I've just used T as
-
40:29 - 40:31my short name here.
-
40:31 - 40:31The iterator
-
40:31 - 40:35looks the same; the bracketing looks the same. I see the end now and I'd
-
40:35 - 40:38like to be able to print vectors of strings, vectors of ints, vector of
-
40:38 - 40:39doubles
-
40:39 - 40:43with this one piece of code. So if I call print vector and I pas code vector events,
-
40:43 - 40:43all's good;
-
40:43 - 40:47vector doubles, all's good; vector strings, all's good.
-
40:47 - 40:50Here's where I could get a little bit into trouble here.
-
40:50 - 40:52I've made this [inaudible] chord that has an X
-
40:52 - 40:57and a Y field. I make a vector that contains these chords.
-
40:57 - 41:00And then I try to call print vector of C.
-
41:00 - 41:03So when I do this, right,
-
41:03 - 41:06it will instantiate a versive print vector
-
41:06 - 41:11where the T has been matched up to, oh it's chords that are in there; you've got a vector
-
41:11 - 41:12of chords.
-
41:12 - 41:15And so okay, we'll go through and iterate over the sides of the vector
-
41:15 - 41:18and this line is trying to say see out
-
41:18 - 41:21of a chord type. And
-
41:21 - 41:22struts
-
41:22 - 41:26don't automatically know how to out put themselves onto a string,
-
41:26 - 41:30and so at this point when I try to instantiate, so the code in print vector is
-
41:30 - 41:33actually fine and works for a large number of types, all the primitive types
-
41:33 - 41:35will be fine,
-
41:35 - 41:36string and things like that are fine.
-
41:36 - 41:40But if I try to use it for a type for which it doesn't have this output
-
41:40 - 41:43behavior, right I will get a compiler error,
-
41:43 - 41:46and it may come as a surprise because a print vector appeared to be working fine in all the other
-
41:46 - 41:49situations and all the sudden it seems like a new error has cropped up
-
41:49 - 41:51but that error came from
-
41:51 - 41:54the instantiation of a particular version in this case, that suddenly ran
-
41:54 - 41:58afoul of what the template expected of the type.
-
41:58 - 42:02The message you get, let's say in X code looks like this, no match for
-
42:02 - 42:08operator, less than, less than in standard CL, vector element, operator [inaudible].
-
42:08 - 42:12So I'm trying to give you a little clue, but in its very cryptic C++ way of what
-
42:12 - 42:15you've done wrong.
-
42:15 - 42:18So it comes back to what the template has to be a little bit clear about
-
42:18 - 42:20from a client point of view is to say well
-
42:20 - 42:24what is it that needs to be true. Will it really work for all types or is there
-
42:24 - 42:27something special about the kind of things that actually need to be true
-
42:27 - 42:29about what's filled in there with a placeholder to make the rest of the code
-
42:29 - 42:31work correctly.
-
42:31 - 42:33So if it uses string insertion
-
42:33 - 42:36or it compares to elements using equals equals, right,
-
42:36 - 42:40something like a strut doesn't by default have those behaviors and so you
-
42:40 - 42:44could have a template that would work for primitive types or types that have these
-
42:44 - 42:47operations declared, but wouldn't work when
-
42:47 - 42:51you gave it a more complex type that didn't have that
-
42:51 - 42:53data support in there.
-
42:53 - 42:55So I have that peace code over here. I can just
-
42:55 - 42:59show it to you. I just took it down here.
-
42:59 - 43:05This is print vector and
-
43:05 - 43:07it's a little bit of
-
43:07 - 43:10template.
-
43:10 - 43:11And
-
43:11 - 43:14if I were to have a vector
-
43:14 - 43:17declared of ints,
-
43:17 - 43:20I say print vector, V
-
43:20 - 43:24that this compiles, there's nothing to print. It turns out it'll just print empty line because
-
43:24 - 43:32there's nothing in there, but if I change this to be chord T
-
43:32 - 43:37and my build is failing, right, and the error message I'm getting here is no match for
-
43:37 - 43:38trying to
-
43:38 - 43:41output that thing and it tells me that all the things I can output on a string. Well, it could be that you could output a
-
43:41 - 43:44[inaudible] but it's not one of those things, right, chord T
-
43:44 - 43:48doesn't have
-
43:48 - 43:51a built-in behavior for outputting to a stream.
-
43:51 - 43:53So this is going to come back to be kind of important because I'm gonna
-
43:53 - 43:54keep going here
-
43:54 - 43:58is that
-
43:58 - 44:00when we get to the sort, right, when
-
44:00 - 44:02we try to build this thing, we're gonna definitely be depending on
-
44:02 - 44:05something being true about the elements, right,
-
44:05 - 44:07that's gonna constrain what the type could be.
-
44:07 - 44:10So this is selection sort in
-
44:10 - 44:14its ordinary form, nothing special about it other than the fact that I
-
44:14 - 44:17changed it as so sorting an int, it's the sort of vector with
-
44:17 - 44:18placeholder type. So it's [inaudible] with
-
44:18 - 44:23the template typed in header, vector of type and then in here,
-
44:23 - 44:26operations like this really are accessing a type
-
44:26 - 44:28and another type
-
44:28 - 44:30variable out of
-
44:30 - 44:33the vector that was passed and then comparing them, which is smaller to decide
-
44:33 - 44:34which index.
-
44:34 - 44:36It's using a swap
-
44:36 - 44:39and so the generic swap would also be necessary for this so that we need to
-
44:39 - 44:42have a swap for any kind of things we want to exchange. We have a template
-
44:42 - 44:44up there for swap,
-
44:44 - 44:47then the sort can build on top of that and use that as part of its workings which is then able
-
44:47 - 44:48to come under
-
44:48 - 44:52swap to any two things can be swapped using the same strategy.
-
44:52 - 44:55And this is actually where templates really start to shine. Like swap in itself isn't that
-
44:55 - 44:56
-
44:56 - 44:59stunning of an example, because you think whatever, who cares if three lines a code, but every
-
44:59 - 45:00
-
45:00 - 45:01little bit does count,
-
45:01 - 45:04but once we get to things like sorting where we could build a really
-
45:04 - 45:05killer
-
45:05 - 45:09totally tuned, really high performance, you know, protection against a [inaudible]
-
45:09 - 45:09quick sort
-
45:09 - 45:12and we want to be sure that we can use it in all the places we need to sort. I don't to
-
45:12 - 45:15make it sort just strings and later when I need to sort for integers, I need to
-
45:15 - 45:18copy and paste it and change string to everywhere,
-
45:18 - 45:21and then if I find a bug in one, I forget to change it in the other I have
-
45:21 - 45:23the bug still lurking there.
-
45:23 - 45:25And so template functions are generally used for
-
45:25 - 45:29all kinds of algorithmically interesting things, sorting and searching and removing
-
45:29 - 45:32duplicates and permuting and finding the mode
-
45:32 - 45:33and
-
45:33 - 45:36shuffling and all these things that like okay, no matter what the type of
-
45:36 - 45:38thing you're working on,
-
45:38 - 45:41the algorithm for how you do it looks the same whether it's ints or
-
45:41 - 45:43strings or whatever. So
-
45:43 - 45:46we got this guy
-
45:46 - 45:46
-
45:46 - 45:49and as is, right, we could
-
45:49 - 45:53push vectors of ints in there, vectors of strings in there and the right thing
-
45:53 - 45:57would work for those without any changes to it,
-
45:57 - 45:59but it does have a lurking
-
45:59 - 46:02constraint on what much be true about the kind of elements that we're
-
46:02 - 46:04trying to sort here.
-
46:04 - 46:05Not every type will work. If
-
46:05 - 46:07I go back to my chord example,
-
46:07 - 46:09this XY,
-
46:09 - 46:13if have a vector of chord and I pass it to sort and if I go back and look at the
-
46:13 - 46:14code,
-
46:14 - 46:17you think about instantiating this with vector, is all chord in here, all the way
-
46:17 - 46:18through here,
-
46:18 - 46:22this part's fine; this part's fine; this part's fine, but suddenly you get to this line and
-
46:22 - 46:25that's gonna be taking two coordinate structures and saying is this coordinate
-
46:25 - 46:27structure less than another.
-
46:27 - 46:30And that code's not gonna compile. Yes. Back when we were doing sets, we were able to explicitly
-
46:30 - 46:36say how this works. Yeah, so you're right where I'm gonna be, but I'm probably
-
46:36 - 46:40not gonna finish today, but I'll have to finish up on Wednesday is we're gonna do exactly what
-
46:40 - 46:43Seth did, and what did Seth do? Comparison function.
-
46:43 - 46:46That's right, he used a comparison function, so you have to have some coordination here when you say,
-
46:46 - 46:49well instead of trying to use the operate or less than on these things,
-
46:49 - 46:53how about the client tell me as part of calling sort, why don't you give me the
-
46:53 - 46:57information in the form of a function that says call me back and tell me are
-
46:57 - 46:59these things less than
-
46:59 - 47:02and so on and how to order them. So that's exactly what we need to do, but I can't
-
47:02 - 47:05really show you the code right now, but I'll just kind of like
-
47:05 - 47:09flash it up there and we will talk about it on Wednesday, what changes make
-
47:09 - 47:12that happen. We'll pick up
-
47:12 - 47:22with Chapter 8, actually after the midterm in terms of
-
47:22 - 47:23reading.
- Title:
- Lecture 16 | Programming Abstractions (Stanford)
- Description:
-
Lecture 16 by Julie Zelenski for the Programming Abstractions Course (CS106B) in the Stanford Computer Science Department.
Julie continues with sorting, specifically quadratic and linearithmic sorting methods, and then explains how to reasonably partition data sets for quicksort. Thereafter, she proceeds to go over different functional templates for sorting algorithms and also briefly goes over instantiation errors and how to fix them.
Complete Playlist for the Course:
http://www.youtube.com/view_play_list?p=FE6E58F856038C69CS 106B Course Website:
http://cs106b.stanford.eduStanford Center for Professional Development:
http://scpd.stanford.edu/Stanford University:
http://www.stanford.edu/Stanford University Channel on YouTube:
http://www.youtube.com/stanforduniversity/ - Video Language:
- English
- Duration:
- 47:35
N. Ueda edited English subtitles for Lecture 16 | Programming Abstractions (Stanford) | ||
Eunjeong_Kim added a translation |