1 00:00:00,090 --> 00:00:02,631 ANNOUNCER: The following content is provided under a Creative 2 00:00:02,631 --> 00:00:04,059 Commons license. 3 00:00:04,059 --> 00:00:06,360 Your support will help MIT OpenCourseWare 4 00:00:06,360 --> 00:00:10,720 continue to offer high quality educational resources for free. 5 00:00:10,720 --> 00:00:13,320 To make a donation or view additional materials 6 00:00:13,320 --> 00:00:17,280 from hundreds of MIT courses, visit MIT OpenCourseWare 7 00:00:17,280 --> 00:00:20,485 at ocw@mit.edu 8 00:00:20,485 --> 00:00:22,860 PROFESSOR: So today we're going to cover a data structure 9 00:00:22,860 --> 00:00:24,240 called link-cut trees. 10 00:00:24,240 --> 00:00:27,300 A cool way of maintaining dynamic trees, 11 00:00:27,300 --> 00:00:29,910 and it begins our study of dynamic graphs. 12 00:00:29,910 --> 00:00:32,850 Where in general, we have a graph usually undirected. 13 00:00:32,850 --> 00:00:35,710 You want to support insertion and deletion of edges. 14 00:00:35,710 --> 00:00:38,970 So we're going to do that in the situation where at all times 15 00:00:38,970 --> 00:00:40,190 our graphs are trees. 16 00:00:40,190 --> 00:00:42,420 So in general, we have a forest of trees 17 00:00:42,420 --> 00:00:44,440 and we want to maintain them. 18 00:00:44,440 --> 00:00:49,229 So that will be our only data structure today 19 00:00:49,229 --> 00:00:50,520 because it's a bit complicated. 20 00:00:50,520 --> 00:00:53,370 It's going to need some fancy amortization. 21 00:00:53,370 --> 00:00:56,880 And two techniques for splitting trees 22 00:00:56,880 --> 00:00:58,650 into paths, one we've seen already 23 00:00:58,650 --> 00:01:00,570 in the context of tango trees and lecture's 24 00:01:00,570 --> 00:01:02,514 six, preferred paths. 25 00:01:02,514 --> 00:01:03,930 And another, which we haven't seen 26 00:01:03,930 --> 00:01:07,200 is probably my favorite technique in data structures, 27 00:01:07,200 --> 00:01:09,847 actually, heavy like decomposition. 28 00:01:09,847 --> 00:01:12,180 The technique and data structure that I've used the most 29 00:01:12,180 --> 00:01:14,120 outside of data structures. 30 00:01:14,120 --> 00:01:16,111 It's very useful in lots of settings. 31 00:01:16,111 --> 00:01:17,610 Whenever you have an unbalanced tree 32 00:01:17,610 --> 00:01:22,720 and you want to make it balance, like with like cut trees, 33 00:01:22,720 --> 00:01:25,030 It's the go to tool. 34 00:01:25,030 --> 00:01:29,955 So, in, general we want to maintain a forest of trees. 35 00:01:37,740 --> 00:01:41,515 And these are going to be rooted unordered trees. 36 00:01:45,270 --> 00:01:47,650 So arbitrary degree I this. 37 00:01:50,700 --> 00:01:53,070 And we have a bunch of operations we want to do. 38 00:01:53,070 --> 00:01:55,650 Basically, insertion and deletion of edges and some 39 00:01:55,650 --> 00:01:57,060 queries. 40 00:01:57,060 --> 00:01:59,340 And we want to do all of those operations 41 00:01:59,340 --> 00:02:00,990 in the log n time per operation. 42 00:02:04,980 --> 00:02:06,780 That's the hard part. 43 00:02:06,780 --> 00:02:12,360 So we have some kind of getting started operation make tree. 44 00:02:12,360 --> 00:02:17,430 This is going to be make a new vertex in a new tree, return. 45 00:02:17,430 --> 00:02:18,040 It. 46 00:02:18,040 --> 00:02:20,700 So this is how you add notes to the structure. 47 00:02:20,700 --> 00:02:23,160 And we're not going to worry about doing deletions. 48 00:02:23,160 --> 00:02:26,744 Once you add something it stays there forever. 49 00:02:26,744 --> 00:02:28,035 So you could you could do that. 50 00:02:28,035 --> 00:02:29,570 It's no big deal. 51 00:02:29,570 --> 00:02:31,650 You could throw away a tree. 52 00:02:31,650 --> 00:02:33,350 Then we have link which is essentially 53 00:02:33,350 --> 00:02:35,790 the insertion of an edge. 54 00:02:35,790 --> 00:02:39,030 So here we're given two vertices BMW 55 00:02:39,030 --> 00:02:42,540 that are in different trees as a precondition. 56 00:02:42,540 --> 00:02:46,590 So v has to be at the root of its tree. 57 00:02:46,590 --> 00:02:48,870 W can be any node. 58 00:02:48,870 --> 00:02:53,580 So here we have another tree and we have some node w inside v 59 00:02:53,580 --> 00:02:59,760 And the link operation adds V as a child of W. 60 00:02:59,760 --> 00:03:03,530 So we add this edge. 61 00:03:03,530 --> 00:03:06,889 OK, that, of course, combines two trees into one tree. 62 00:03:06,889 --> 00:03:09,180 And the requirement is BMW has to be in different trees 63 00:03:09,180 --> 00:03:10,888 or otherwise you'd be adding a cycle that 64 00:03:10,888 --> 00:03:15,710 doesn't satisfy that were always a forest of trees. 65 00:03:15,710 --> 00:03:23,340 Then we have a cut operation, which is basically the reverse. 66 00:03:23,340 --> 00:03:25,260 So let me draw it. 67 00:03:25,260 --> 00:03:30,090 We have V subtree parent. 68 00:03:30,090 --> 00:03:33,120 And there is a whole tree up here. 69 00:03:36,130 --> 00:03:40,350 And what we want to do is remove that edge. 70 00:03:40,350 --> 00:03:43,590 So that splits one tree into two trees by the leading 71 00:03:43,590 --> 00:03:44,970 edge from V to its parent. 72 00:03:54,800 --> 00:03:57,570 OK so those are our updates. 73 00:03:57,570 --> 00:04:01,830 Pretty obvious in the setting of dynamic graphs. 74 00:04:01,830 --> 00:04:04,690 Of course, it's the first time we see them. 75 00:04:04,690 --> 00:04:05,812 Now we have some queries. 76 00:04:05,812 --> 00:04:07,270 There are lots of different queries 77 00:04:07,270 --> 00:04:09,940 that cut-trees can support. 78 00:04:09,940 --> 00:04:18,430 One of the most basic is find the root of vertex. 79 00:04:18,430 --> 00:04:19,750 Let me just draw a picture of. 80 00:04:19,750 --> 00:04:24,460 It you have some vertex V, you want 81 00:04:24,460 --> 00:04:27,360 to return the root of the tree. 82 00:04:27,360 --> 00:04:34,160 So find R. And that's pretty easy to do. 83 00:04:34,160 --> 00:04:38,570 Well actually see it in next class, next lecture, 84 00:04:38,570 --> 00:04:40,940 if you wanted to make tree/link cut and find root, 85 00:04:40,940 --> 00:04:44,450 there's a really easy way to do them in logarithmic time. 86 00:04:44,450 --> 00:04:47,090 link-cut trees is a harder way to do it in log n time, 87 00:04:47,090 --> 00:04:49,710 but they support a lot of other operations. 88 00:04:49,710 --> 00:04:59,020 And in particular, something called path aggregation. 89 00:04:59,020 --> 00:05:04,420 This is kind of the essence of link/cut are cool. 90 00:05:04,420 --> 00:05:07,790 Let's suppose you have a for a tree, 91 00:05:07,790 --> 00:05:13,210 you have a vertex V. There's a root to V path. 92 00:05:13,210 --> 00:05:15,850 And let's suppose that every node or every edge, doesn't 93 00:05:15,850 --> 00:05:17,530 matter, has a weight on it. 94 00:05:17,530 --> 00:05:19,700 Just some real number. 95 00:05:19,700 --> 00:05:22,150 Then path aggregation can do things 96 00:05:22,150 --> 00:05:27,850 like the min or the max or the sum 97 00:05:27,850 --> 00:05:31,705 or the product or whatever of weights on that path. 98 00:05:41,102 --> 00:05:42,310 And this is a powerful thing. 99 00:05:42,310 --> 00:05:44,768 And it's actually the reason link/cut trees were originally 100 00:05:44,768 --> 00:05:47,110 invented for doing network flow algorithms faster. 101 00:05:47,110 --> 00:05:49,519 If you know network flow algorithms. 102 00:05:49,519 --> 00:05:51,560 Or maybe you've seen them in advanced algorithms. 103 00:05:51,560 --> 00:05:53,440 This is sort of the key thing you need to do. 104 00:05:53,440 --> 00:05:58,270 You find, I think, min way edge along one of these paths 105 00:05:58,270 --> 00:06:01,170 and that's the max you can push in a push reliable strategy. 106 00:06:01,170 --> 00:06:03,670 I don't want to get into that because that's algorithms, not 107 00:06:03,670 --> 00:06:05,000 data structures. 108 00:06:05,000 --> 00:06:06,670 But this is why they were invented. 109 00:06:06,670 --> 00:06:11,230 And, in general, link/cut trees have a very strong kind 110 00:06:11,230 --> 00:06:12,652 of path thing. 111 00:06:12,652 --> 00:06:14,360 If you want to know anything about a root 112 00:06:14,360 --> 00:06:18,100 to the path for any node v, link-cut trees 113 00:06:18,100 --> 00:06:20,030 can do whatever you want in lon n time. 114 00:06:20,030 --> 00:06:22,310 This is just sort of an example of that. 115 00:06:22,310 --> 00:06:24,750 And Yeah. 116 00:06:24,750 --> 00:06:25,290 course. 117 00:06:25,290 --> 00:06:27,370 So that's what link countries are able to do. 118 00:06:27,370 --> 00:06:31,060 All these operations in log n And the main point here 119 00:06:31,060 --> 00:06:34,540 is that the trees are storing are probably not balanced. 120 00:06:34,540 --> 00:06:38,120 It could be a path, could be depth 121 00:06:38,120 --> 00:06:41,770 and is this path we're talking about could be length order 122 00:06:41,770 --> 00:06:44,320 n is really bad. 123 00:06:44,320 --> 00:06:46,704 And yet, we can do all these operations in log n time. 124 00:06:46,704 --> 00:06:48,370 And we're going to do that, essentially, 125 00:06:48,370 --> 00:06:52,240 by storing the unbalanced tree that you're 126 00:06:52,240 --> 00:06:57,010 trying to represent, which we call this the represent tree. 127 00:06:57,010 --> 00:07:00,430 We're going to store it using, essentially, a balanced tree. 128 00:07:00,430 --> 00:07:01,870 In one version of link-cut trees, 129 00:07:01,870 --> 00:07:06,180 indeed, we store all the nodes in a log n height tree. 130 00:07:06,180 --> 00:07:08,380 The version we're going to cover here-- 131 00:07:08,380 --> 00:07:10,600 there's several versions of link-cut trees. 132 00:07:10,600 --> 00:07:15,580 Original are biased later in Tarjan in 1983. 133 00:07:15,580 --> 00:07:18,520 And then Tarjan wrote a book, one of a few books 134 00:07:18,520 --> 00:07:19,750 on data structures. 135 00:07:19,750 --> 00:07:23,980 Very thin book, usually called Tarjan's little book, in 1984. 136 00:07:23,980 --> 00:07:26,160 And it has a different version of link-cut trees, 137 00:07:26,160 --> 00:07:27,576 and that's the version we're going 138 00:07:27,576 --> 00:07:29,609 to cover it uses splay trees as a subroutine. 139 00:07:29,609 --> 00:07:31,400 So it's not going to be perfectly balanced. 140 00:07:31,400 --> 00:07:33,930 It's going to be balanced in an amortize sense, 141 00:07:33,930 --> 00:07:38,320 or vaguely balanced, roughly balanced, whatever. 142 00:07:38,320 --> 00:07:41,530 But there is a version that does everything in log n worse case 143 00:07:41,530 --> 00:07:42,130 pre-operation. 144 00:07:42,130 --> 00:07:45,850 If there's time, I'll sketch that for you at the end. 145 00:07:45,850 --> 00:07:50,260 But the simplest version I know is this splay tree version. 146 00:07:50,260 --> 00:07:55,120 And it's also kind of fun because the version we'll see, 147 00:07:55,120 --> 00:07:56,950 doesn't really look like it should work, 148 00:07:56,950 --> 00:08:01,550 and yet it does thanks to splay trees, essentially. 149 00:08:01,550 --> 00:08:03,970 So it's a little, it's fun and surprising in that sense. 150 00:08:15,610 --> 00:08:20,214 As I said, link-cut trees are all about paths in the tree. 151 00:08:20,214 --> 00:08:22,380 And so somehow we want to split a tree up into paths 152 00:08:22,380 --> 00:08:24,210 and we've already seen a way to do this. 153 00:08:24,210 --> 00:08:26,290 The preferred path decomposition. 154 00:08:26,290 --> 00:08:29,970 So it's kind of reminding you, but I'm also 155 00:08:29,970 --> 00:08:33,230 going to slightly redefine it, if I recall correctly. 156 00:08:33,230 --> 00:08:38,209 It's just a minor difference which 157 00:08:38,209 --> 00:08:39,669 I can talk about a second. 158 00:08:39,669 --> 00:08:42,900 The notion of a preferred child of a node, and it's 159 00:08:42,900 --> 00:08:43,875 going to be two cases. 160 00:08:47,770 --> 00:08:53,960 There isn't a preferred child, if the last access 161 00:08:53,960 --> 00:09:04,020 in these subtree is v. So we have some node v. Now, 162 00:09:04,020 --> 00:09:07,430 this is relative to the represented tree. 163 00:09:07,430 --> 00:09:10,260 So we have some node to v. We don't care about accesses 164 00:09:10,260 --> 00:09:13,350 outside of that subtree, but of the last access within 165 00:09:13,350 --> 00:09:17,730 the subtree was v itself, then there's no preferred child. 166 00:09:17,730 --> 00:09:20,220 Otherwise, the last access within the tree 167 00:09:20,220 --> 00:09:22,900 was in one of these child subtrees. 168 00:09:22,900 --> 00:09:25,980 And whichever one it was, we say w is the preferred child. 169 00:09:29,020 --> 00:09:42,091 So if the last access in v subtree is in child w's 170 00:09:42,091 --> 00:09:42,590 subtree. 171 00:09:45,430 --> 00:09:47,630 OK, I think last time we defined preferred children 172 00:09:47,630 --> 00:09:50,930 in the context of tango trees, we just had the second part. 173 00:09:50,930 --> 00:09:53,330 So if there is an access to v, we ignored it 174 00:09:53,330 --> 00:09:55,460 and we just consider what the last child access. 175 00:09:55,460 --> 00:09:57,470 Was I don't think there's actually 176 00:09:57,470 --> 00:09:59,120 would affect tango trees, but I think 177 00:09:59,120 --> 00:10:00,440 it does effect Link-cut trees. 178 00:10:00,440 --> 00:10:02,180 So I want to define it this way. 179 00:10:02,180 --> 00:10:05,390 It'll make life cleaner, basically. 180 00:10:05,390 --> 00:10:08,210 Probably not a huge difference either way. 181 00:10:08,210 --> 00:10:09,980 OK, once you have preferred children, 182 00:10:09,980 --> 00:10:13,250 that gives you one outgoing edge, downward edge, 183 00:10:13,250 --> 00:10:14,720 from every node. 184 00:10:14,720 --> 00:10:21,620 And so we get preferred paths by repeatedly following 185 00:10:21,620 --> 00:10:23,090 preferred child pointers. 186 00:10:23,090 --> 00:10:27,250 Now, we may stop at some point because we reach a none. 187 00:10:27,250 --> 00:10:31,610 I'm going to use none as like null pointers in this lecture. 188 00:10:31,610 --> 00:10:34,910 But, in general, we have some tree and you follow for a while 189 00:10:34,910 --> 00:10:38,450 and then it's going to be a bunch of things like this. 190 00:10:38,450 --> 00:10:49,430 We decompose the nodes and the represented tree, 191 00:10:49,430 --> 00:10:50,460 partition the nodes. 192 00:10:54,350 --> 00:10:57,110 Every node belongs to some preferred path. 193 00:10:57,110 --> 00:11:00,770 So basic idea is we're going to store the preferred 194 00:11:00,770 --> 00:11:05,720 paths in kind of balanced binary search trees, splay trees, 195 00:11:05,720 --> 00:11:08,330 and then we're going to connect them together because that's 196 00:11:08,330 --> 00:11:10,770 not all the edges in the tree. 197 00:11:10,770 --> 00:11:15,810 There's some edges that sort of connect them, 198 00:11:15,810 --> 00:11:16,970 connect the paths together. 199 00:11:16,970 --> 00:11:19,670 That's where the tree part comes in. 200 00:11:19,670 --> 00:11:22,700 That's what we're going to do it this thing is unbalanced. 201 00:11:22,700 --> 00:11:25,190 We're going to take each of these white lines 202 00:11:25,190 --> 00:11:28,190 and compress it into a splay tree, 203 00:11:28,190 --> 00:11:29,590 and preserve the red pointers. 204 00:11:33,721 --> 00:11:37,090 I'll write that down. 205 00:11:37,090 --> 00:11:41,350 These are called auxiliary trees. 206 00:11:41,350 --> 00:11:44,760 This was exactly the idea and tango trace 207 00:11:44,760 --> 00:11:48,310 and I'm using tango tree terminology 208 00:11:48,310 --> 00:11:50,880 to keep it consistent with that notation. 209 00:11:50,880 --> 00:11:54,700 It wasn't called preferred paths in the link-cut tree papers. 210 00:11:54,700 --> 00:11:58,270 Or it wasn't called auxiliary trees, but same difference. 211 00:11:58,270 --> 00:12:06,940 So auxiliary trees were going to store represent each preferred 212 00:12:06,940 --> 00:12:16,380 path by a splay tree. 213 00:12:16,380 --> 00:12:21,079 Tango trees we use red-black trees or whatever. 214 00:12:21,079 --> 00:12:22,662 Could us splay trees, actually, if you 215 00:12:22,662 --> 00:12:25,540 use tango trees with splay trees for each preferred path. 216 00:12:25,540 --> 00:12:27,650 It's called a multi-splay tree. 217 00:12:27,650 --> 00:12:31,020 Multi-splay trees are almost identical to link-cut trees 218 00:12:31,020 --> 00:12:32,770 but, they're used for a different setting. 219 00:12:32,770 --> 00:12:37,380 The use for proving log n competitiveness. 220 00:12:37,380 --> 00:12:40,210 Here we're doing it to represent a specific tree. 221 00:12:40,210 --> 00:12:43,420 With tango trees, the tree we're representing 222 00:12:43,420 --> 00:12:45,190 was just a perfect binary tree, p. 223 00:12:45,190 --> 00:12:48,179 So you may recall, here it has some meaning. 224 00:12:48,179 --> 00:12:49,720 And it's going to be changing, and we 225 00:12:49,720 --> 00:12:53,060 care about how it's changing. 226 00:12:53,060 --> 00:12:57,520 OK, another difference is we're going to key the nodes 227 00:12:57,520 --> 00:12:59,290 by depth. 228 00:12:59,290 --> 00:13:02,844 This is what we wanted to do with tango trees, 229 00:13:02,844 --> 00:13:04,510 but we weren't allowed to because we had 230 00:13:04,510 --> 00:13:05,676 to be a binary search trees. 231 00:13:05,676 --> 00:13:07,420 And the keys were given to us. 232 00:13:07,420 --> 00:13:08,650 Here, there are no keys. 233 00:13:08,650 --> 00:13:11,320 So we need to specify them and the most convenient one 234 00:13:11,320 --> 00:13:12,530 is by depth. 235 00:13:12,530 --> 00:13:19,790 So we're just taking a path like this, 0, 1, 2, 3 4. 236 00:13:19,790 --> 00:13:23,470 And then we're turning it into a nice balance tree 237 00:13:23,470 --> 00:13:33,430 like this, 0, 1, 2, 3, 3, 4. 238 00:13:33,430 --> 00:13:38,080 OK, Now, it's a splay trees so it's not 239 00:13:38,080 --> 00:13:40,270 guaranteed to be balanced at any moment, 240 00:13:40,270 --> 00:13:45,670 but amortized is going to have log n performance preparation. 241 00:13:45,670 --> 00:13:48,280 OK, and then this is sort of that's 242 00:13:48,280 --> 00:13:49,990 representing each of these white paths, 243 00:13:49,990 --> 00:13:52,040 but then we also need the red pointers. 244 00:13:52,040 --> 00:13:55,360 So what we're going to do is say the root 245 00:13:55,360 --> 00:13:59,140 of each auxiliary tree, I'll abbreviate 246 00:13:59,140 --> 00:14:08,410 ox tree, stores what I'll call the path parent, which 247 00:14:08,410 --> 00:14:11,080 are these red pointers. 248 00:14:11,080 --> 00:14:25,240 The definition is this is, the paths, the top nodes, parent, 249 00:14:25,240 --> 00:14:26,650 and represented tree. 250 00:14:33,220 --> 00:14:36,760 OK, very soon it's going to get confusing 251 00:14:36,760 --> 00:14:38,710 and I'm going to always make it explicit. 252 00:14:38,710 --> 00:14:40,780 Am I talking about the represented tree the thing 253 00:14:40,780 --> 00:14:42,670 we're trying to represent? 254 00:14:42,670 --> 00:14:46,690 Or am I talking about auxiliary trees because notion of parent 255 00:14:46,690 --> 00:14:48,700 is different in the two? 256 00:14:48,700 --> 00:14:50,770 So in an auxiliary tree a parent is just 257 00:14:50,770 --> 00:14:54,010 whatever it happens to be stored in the splay tree. 258 00:14:54,010 --> 00:14:56,710 When you splay operations you care about those parents. 259 00:14:56,710 --> 00:14:59,830 When you're thinking about the tree you're 260 00:14:59,830 --> 00:15:01,870 trying to represent, you care about parents 261 00:15:01,870 --> 00:15:03,680 in the represented tree. 262 00:15:03,680 --> 00:15:04,930 Now, how do you see that here? 263 00:15:04,930 --> 00:15:09,124 Well following parent is like doing predecessor over here. 264 00:15:09,124 --> 00:15:10,790 So we kind of know how to do predecessor 265 00:15:10,790 --> 00:15:12,480 in a binary search tree. 266 00:15:12,480 --> 00:15:16,060 But when we get to 0, which is the left most 267 00:15:16,060 --> 00:15:20,170 node in this tree, corresponds to the top of the path, 268 00:15:20,170 --> 00:15:24,130 if we want to do the parent that's going up from this path, 269 00:15:24,130 --> 00:15:26,580 that's going to be the path parent. 270 00:15:26,580 --> 00:15:28,930 And it saying the path's top node, 271 00:15:28,930 --> 00:15:32,620 that's this guy 0, its parent and the representative tree 272 00:15:32,620 --> 00:15:34,240 are just going to store that pointer. 273 00:15:34,240 --> 00:15:35,290 The only weird thing is we're not 274 00:15:35,290 --> 00:15:37,090 going to store the pointer here, we're 275 00:15:37,090 --> 00:15:40,420 going to store the pointer here. 276 00:15:40,420 --> 00:15:41,410 That's the path parent. 277 00:15:41,410 --> 00:15:43,750 We're going to put it at the root of the splay tree, 278 00:15:43,750 --> 00:15:45,166 basically because it's really easy 279 00:15:45,166 --> 00:15:46,510 to get to the root of a tree. 280 00:15:46,510 --> 00:15:48,400 You could probably start here, you just 281 00:15:48,400 --> 00:15:51,180 have to go left every time and it's kind of annoying. 282 00:15:51,180 --> 00:15:52,900 Analysis will get messier. 283 00:15:52,900 --> 00:15:54,940 So we'll put at the root. 284 00:15:54,940 --> 00:15:56,890 And so, in particular, if I do a rotation, 285 00:15:56,890 --> 00:15:59,740 like if I rotate the tree like this and make one the route, 286 00:15:59,740 --> 00:16:01,840 that path parent pointer has to move to 1. 287 00:16:01,840 --> 00:16:03,580 But it's still representing essentially 288 00:16:03,580 --> 00:16:05,680 for this whole splay tree representing 289 00:16:05,680 --> 00:16:10,340 this path, what was the parent pointer from there. 290 00:16:10,340 --> 00:16:13,690 So this is the represented tree, and this is the ox tree. 291 00:16:16,600 --> 00:16:20,290 OK, now if I take all the ox trees plus these parent 292 00:16:20,290 --> 00:16:25,180 pointers, I get something called the tree of ox trees. 293 00:16:30,760 --> 00:16:34,450 And this is our representation. 294 00:16:34,450 --> 00:16:37,180 So there's the represented thing versus our representation. 295 00:16:37,180 --> 00:16:39,471 I'm not going to use the word representation because it 296 00:16:39,471 --> 00:16:41,200 sounds almost like represented. 297 00:16:41,200 --> 00:16:44,350 So it's going to be represented versus tree of ox trees. 298 00:16:44,350 --> 00:16:45,940 Tree of ox trees is what we store, 299 00:16:45,940 --> 00:16:48,670 represented is what we want to store. 300 00:16:48,670 --> 00:16:51,700 That's what we're trying to represent. 301 00:16:51,700 --> 00:16:57,160 So that's the terminology, Basically, we 302 00:16:57,160 --> 00:16:59,080 want the tree of ox trees to be balanced, 303 00:16:59,080 --> 00:17:01,413 and if there's splay trees, they'll be kind of balanced. 304 00:17:04,390 --> 00:17:08,119 Whereas, the represented tree is on balance. 305 00:17:08,119 --> 00:17:10,990 Cool so now I want to give you some code 306 00:17:10,990 --> 00:17:13,201 and how we're going to manipulate these things. 307 00:17:13,201 --> 00:17:14,950 And then we'll be able to analyze the code 308 00:17:14,950 --> 00:17:17,619 and that both will take a little while. 309 00:17:42,871 --> 00:17:44,620 The main operation I'm going to talk about 310 00:17:44,620 --> 00:17:47,050 is actually just a helper operation. 311 00:17:47,050 --> 00:17:52,820 So first I want to tell you what it is, how it works. 312 00:17:52,820 --> 00:17:56,530 It's like an access in a tango tree. 313 00:17:56,530 --> 00:18:00,100 With tango trees we just wanted to touch item xi 314 00:18:00,100 --> 00:18:02,316 and then go onto the next item, xi plus 1. 315 00:18:02,316 --> 00:18:03,940 So I'm going to think about that world, 316 00:18:03,940 --> 00:18:06,275 while all I'm trying to do is touch nodes. 317 00:18:06,275 --> 00:18:07,900 What's interesting about touching nodes 318 00:18:07,900 --> 00:18:12,590 is it changes this notion of preferred edges. 319 00:18:12,590 --> 00:18:14,830 So, as I said, the last access in that subtree 320 00:18:14,830 --> 00:18:16,340 was blah, blah, blah. 321 00:18:16,340 --> 00:18:17,110 So access. 322 00:18:19,690 --> 00:18:21,550 In reality, what I mean is the last time 323 00:18:21,550 --> 00:18:26,560 that node was used as a link or cut or find operation. 324 00:18:26,560 --> 00:18:28,660 But in fact I'm going to make that explicit. 325 00:18:28,660 --> 00:18:31,630 Every operation is going to start by calling this function 326 00:18:31,630 --> 00:18:33,850 access on its arguments. 327 00:18:33,850 --> 00:18:35,602 Question? 328 00:18:35,602 --> 00:18:37,498 AUDIENCE: I still don't understand. 329 00:18:37,498 --> 00:18:41,710 When you say that this [INAUDIBLE] by depth-- 330 00:18:41,710 --> 00:18:42,646 PROFESSOR: Yes. 331 00:18:42,646 --> 00:18:44,229 AUDIENCE: How do you go from that path 332 00:18:44,229 --> 00:18:45,930 to the actual splay tree? 333 00:18:45,930 --> 00:18:49,160 PROFESSOR: OK so the transformation from this path 334 00:18:49,160 --> 00:18:50,950 in the represented tree to splay tree 335 00:18:50,950 --> 00:18:55,750 is just these nodes have depth within that path, 336 00:18:55,750 --> 00:18:57,850 I mean they're just stored along the path. 337 00:18:57,850 --> 00:19:00,580 What I mean is, I want to store them in as a binary search 338 00:19:00,580 --> 00:19:03,390 tree ordered by that value. 339 00:19:03,390 --> 00:19:06,100 So that's what-- yeah. 340 00:19:06,100 --> 00:19:08,420 So splay trees have some key on the nodes, 341 00:19:08,420 --> 00:19:10,430 they maintain the binary search tree property. 342 00:19:10,430 --> 00:19:11,971 My key is just going to be the depth. 343 00:19:11,971 --> 00:19:13,144 The position along the path. 344 00:19:13,144 --> 00:19:15,352 AUDIENCE: So if you do an in order traversal you just 345 00:19:15,352 --> 00:19:15,880 get the path. 346 00:19:15,880 --> 00:19:17,410 PROFESSOR: Right if I do it in order traversal here, 347 00:19:17,410 --> 00:19:18,830 I'll get the path back. 348 00:19:18,830 --> 00:19:22,750 Yep, no problem. 349 00:19:22,750 --> 00:19:24,830 That's going to be important to understand. 350 00:19:24,830 --> 00:19:29,600 OK, so to do an access, access is going to do two things. 351 00:19:29,600 --> 00:19:31,930 The first thing it has to do, and the other thing 352 00:19:31,930 --> 00:19:35,500 is going to make our life easy, you'll 353 00:19:35,500 --> 00:19:39,080 see once we've defined access, all operations become trivial. 354 00:19:39,080 --> 00:19:41,530 So it's going to be a really cool helper function. 355 00:19:46,580 --> 00:19:49,570 The first thing we have to do, when we access a node v, 356 00:19:49,570 --> 00:19:53,230 is say well that then by definition the path to v from 357 00:19:53,230 --> 00:19:57,937 the root --v to root I guess, sort of, but probably more root 358 00:19:57,937 --> 00:19:58,672 to v-- 359 00:20:03,010 --> 00:20:03,940 should be preferred. 360 00:20:03,940 --> 00:20:05,440 That's the definition of preferred 361 00:20:05,440 --> 00:20:07,231 because now it's the latest thing accessed. 362 00:20:11,859 --> 00:20:12,900 So we've got to fix that. 363 00:20:15,265 --> 00:20:16,890 But we're going to do a little bit more 364 00:20:16,890 --> 00:20:24,530 we're also going to make v the root of its ox tree. 365 00:20:30,270 --> 00:20:33,060 Which will mean, because that ox tree is now 366 00:20:33,060 --> 00:20:36,900 the top most ox tree because that actually contains the root 367 00:20:36,900 --> 00:20:43,830 and it contains v. So in fact, v is the root 368 00:20:43,830 --> 00:20:45,520 of the tree of ox trees. 369 00:20:45,520 --> 00:20:54,420 It's the overall root for this tree of our streets. 370 00:20:54,420 --> 00:20:55,300 Why do we do that? 371 00:20:55,300 --> 00:20:58,047 Well, it's sort of going to just be a consequence of using 372 00:20:58,047 --> 00:20:59,880 splay, because whenever you splice something 373 00:20:59,880 --> 00:21:04,020 you move it to the root in this zigzaggy way. 374 00:21:04,020 --> 00:21:07,200 But it will actually be really helpful to have this property, 375 00:21:07,200 --> 00:21:11,450 and that's why these are the simplest link-cut trees I know. 376 00:21:11,450 --> 00:21:15,300 OK, so how do we do this? 377 00:21:15,300 --> 00:21:18,840 So you're given the node v somewhere in this world, 378 00:21:18,840 --> 00:21:21,480 and we've basically got to fix a lot of preferred child 379 00:21:21,480 --> 00:21:23,892 pointers. 380 00:21:23,892 --> 00:21:25,350 And, whereas, tango trees basically 381 00:21:25,350 --> 00:21:30,420 walked from the top down, navigating one preferred path 382 00:21:30,420 --> 00:21:32,070 until it found the right place to exit 383 00:21:32,070 --> 00:21:35,220 and then fixing that edge, were going to be working bottom up. 384 00:21:35,220 --> 00:21:38,010 Because we already know where the vertexes, were given it, 385 00:21:38,010 --> 00:21:41,280 and we need to walk our way up the tree and kind of push 386 00:21:41,280 --> 00:21:43,620 v to the root overall. 387 00:21:43,620 --> 00:21:50,040 So the first thing to do is splay v. So 388 00:21:50,040 --> 00:21:56,990 that, now, when I say splay v, I mean within its ox tree. 389 00:21:56,990 --> 00:22:00,650 Doesn't make sense to do it in any global sense. 390 00:22:00,650 --> 00:22:04,060 In some sense access is going to be our global version of splay. 391 00:22:04,060 --> 00:22:06,900 Whenever I say splay a node, I mean just within its ox tree. 392 00:22:06,900 --> 00:22:08,900 That's going to be the definition of splay tree. 393 00:22:08,900 --> 00:22:12,380 So you may recall from Lecture Six there's the zig-zig case 394 00:22:12,380 --> 00:22:13,290 and zig-zag case. 395 00:22:13,290 --> 00:22:16,470 You do some rotation, double rotation, whatever. 396 00:22:16,470 --> 00:22:18,840 In the end, maybe one more rotation, and then v 397 00:22:18,840 --> 00:22:20,772 becomes the root. 398 00:22:20,772 --> 00:22:22,230 So what does the picture look like? 399 00:22:22,230 --> 00:22:25,260 We've got v at the root of it's ox tree. 400 00:22:25,260 --> 00:22:27,060 Then we've got things in the left subtree 401 00:22:27,060 --> 00:22:29,461 which have smaller depth. 402 00:22:29,461 --> 00:22:31,710 And then we've got things in the right subtree of tree 403 00:22:31,710 --> 00:22:34,260 which have bigger depth. 404 00:22:34,260 --> 00:22:38,620 Depth bigger than v. So we just pulled to the root. 405 00:22:38,620 --> 00:22:43,350 So in the represented tree what we have is a path v. These 406 00:22:43,350 --> 00:22:46,210 are things of smaller depth these things of larger depth. 407 00:22:46,210 --> 00:22:50,100 Now, if you look at the definition of preferred child, 408 00:22:50,100 --> 00:22:54,480 when we access v, v now no longer has a preferred child. 409 00:22:54,480 --> 00:22:56,945 This preferred child is now none. 410 00:22:56,945 --> 00:22:58,320 If you look at this picture, this 411 00:22:58,320 --> 00:23:02,650 is a preferred path, currently, v has a preferred child. 412 00:23:02,650 --> 00:23:03,870 We want to get rid of that. 413 00:23:03,870 --> 00:23:06,270 That's our first operation. 414 00:23:09,330 --> 00:23:12,390 First thing we want to do is get rid of that edge. 415 00:23:12,390 --> 00:23:15,460 It's no longer a preferred edge. 416 00:23:15,460 --> 00:23:19,670 So that essentially corresponds to this edge 417 00:23:19,670 --> 00:23:22,040 because that's the connection from v to deeper things. 418 00:23:22,040 --> 00:23:24,800 I mean in fact, this node right below us 419 00:23:24,800 --> 00:23:29,530 let's call it x is right here. 420 00:23:29,530 --> 00:23:31,880 It's the smallest depth among the nodes 421 00:23:31,880 --> 00:23:33,860 with larger depth than v. 422 00:23:33,860 --> 00:23:36,080 But if we kind of kill that connection, 423 00:23:36,080 --> 00:23:39,720 then, now, this path is its own thing, the part below v, 424 00:23:39,720 --> 00:23:42,120 separate from v and above. 425 00:23:42,120 --> 00:23:44,210 So that's what we're going to do first. 426 00:23:44,210 --> 00:23:49,340 Remove these preferred child. 427 00:23:53,510 --> 00:23:56,092 And I'm going to elaborate exactly the point arithmetic 428 00:23:56,092 --> 00:23:57,050 that makes that happen. 429 00:23:59,720 --> 00:24:03,770 This is the kind of tedious part of, or really any point 430 00:24:03,770 --> 00:24:05,140 of machine data structure. 431 00:24:05,140 --> 00:24:07,640 This is going to all work on a point of machine, by the way. 432 00:24:25,710 --> 00:24:29,860 OK, so basically I'm obliterating the edge. 433 00:24:29,860 --> 00:24:35,770 So I'm going to make this vertex here, have a path parent 434 00:24:35,770 --> 00:24:41,920 pointer to v and otherwise obliterate this edge. 435 00:24:41,920 --> 00:24:45,160 It will no longer has a parent, v no longer has a right child. 436 00:24:45,160 --> 00:24:50,680 So it's going to be v has a left thing and no right pointer. 437 00:24:50,680 --> 00:24:55,485 But this separate tree is going to a parent pointer to v. 438 00:24:55,485 --> 00:24:56,860 This is, of course, if it exists. 439 00:24:56,860 --> 00:25:01,690 If v.right is nothing already, then you don't do any of this. 440 00:25:01,690 --> 00:25:04,457 But if there is a right pointer then you've got to do this. 441 00:25:04,457 --> 00:25:06,040 So this is the place where we're going 442 00:25:06,040 --> 00:25:09,044 to set path parents, pretty obvious stuff. 443 00:25:09,044 --> 00:25:10,960 The only thing to check is that this is really 444 00:25:10,960 --> 00:25:11,751 in the right place. 445 00:25:11,751 --> 00:25:15,760 This thing is the root of this ox tree, which 446 00:25:15,760 --> 00:25:18,790 is where the parent pointer path parent supposed to be, 447 00:25:18,790 --> 00:25:22,450 and it points to v meaning, that the parent of x 448 00:25:22,450 --> 00:25:24,220 is v in the represented tree. 449 00:25:24,220 --> 00:25:25,930 And that's exactly what this picture is. 450 00:25:25,930 --> 00:25:29,410 This is the represented tree parent of x is v, 451 00:25:29,410 --> 00:25:32,990 and so that's the correct definition of pat parent. 452 00:25:32,990 --> 00:25:34,650 Cool. 453 00:25:34,650 --> 00:25:37,740 OK, now the fun part. 454 00:25:42,419 --> 00:25:43,960 Now, we're going to walk up the tree. 455 00:25:46,891 --> 00:25:49,390 We've seen everything on the outline except this heavy light 456 00:25:49,390 --> 00:25:50,640 decomposition. 457 00:25:50,640 --> 00:25:51,820 We'll come to that soon. 458 00:25:57,480 --> 00:26:01,900 OK, so now we're going to walk up the tree 459 00:26:01,900 --> 00:26:05,710 and add new preferred child pointers. 460 00:26:05,710 --> 00:26:09,070 This is the one that we had to remove because it's 461 00:26:09,070 --> 00:26:12,940 the stuff below v. But up the path, if we walk up to the root 462 00:26:12,940 --> 00:26:16,060 here, to the left most node of v then 463 00:26:16,060 --> 00:26:17,530 there's a path parent from there, 464 00:26:17,530 --> 00:26:21,330 we want to make that not a path parent but a regular parent. 465 00:26:21,330 --> 00:26:23,500 Because that right now, is living 466 00:26:23,500 --> 00:26:25,690 in its own little preferred path that we 467 00:26:25,690 --> 00:26:29,230 want that preferred path to extend all the way to the root, 468 00:26:29,230 --> 00:26:33,050 by the definition of a child after doing an access. 469 00:26:33,050 --> 00:26:42,940 So we're going to do a loop until v path parent is none. 470 00:26:48,800 --> 00:26:52,950 I'm going to let w be v's path parent. 471 00:26:57,470 --> 00:26:59,700 save some writing. 472 00:26:59,700 --> 00:27:02,170 And then we're going to splay w. 473 00:27:02,170 --> 00:27:05,540 OK, I think at this point, I should draw a picture. 474 00:27:05,540 --> 00:27:15,020 So many pictures to draw. 475 00:27:15,020 --> 00:27:21,610 So we have, let's say, a node w as a child v. This 476 00:27:21,610 --> 00:27:25,120 is the represented tree. 477 00:27:25,120 --> 00:27:30,370 That's some other child x and I can have many children. 478 00:27:30,370 --> 00:27:34,060 Let's suppose that, right now, the preferred child from w 479 00:27:34,060 --> 00:27:35,890 is x. 480 00:27:35,890 --> 00:27:38,560 It's not v because we just followed a path parent pointer 481 00:27:38,560 --> 00:27:42,940 to go from v's path, which is something here, to w's path. 482 00:27:42,940 --> 00:27:45,850 So w's path is going to be something like this. 483 00:27:45,850 --> 00:27:48,490 So it goes to some other guy x, we 484 00:27:48,490 --> 00:27:51,610 want change that that pointer. 485 00:27:51,610 --> 00:27:56,160 Instead of being that, we want to go here. 486 00:27:56,160 --> 00:27:58,000 That's in the represented tree. 487 00:27:58,000 --> 00:28:03,610 Now what does this look like in the tree of ox trees? 488 00:28:03,610 --> 00:28:05,340 W lives in some thing. 489 00:28:09,760 --> 00:28:14,260 w's there, x's its successor in there, 490 00:28:14,260 --> 00:28:19,720 so maybe it's like a right child or whatever, 491 00:28:19,720 --> 00:28:21,250 somewhere else in the tree. 492 00:28:21,250 --> 00:28:24,210 And then separately we've already built this thing. 493 00:28:24,210 --> 00:28:28,210 v it has a left child, it has no right child because there's 494 00:28:28,210 --> 00:28:32,680 nothing deeper than v in its own preferred path. 495 00:28:32,680 --> 00:28:35,950 And then we have a path parent pointer that goes like this. 496 00:28:40,070 --> 00:28:40,860 I want to fix. 497 00:28:40,860 --> 00:28:42,860 That the first thing I'm going to do is splay w, 498 00:28:42,860 --> 00:28:46,070 so the w is in the root of its own tree. 499 00:28:46,070 --> 00:28:50,480 So then it's going to look like w. 500 00:28:50,480 --> 00:28:54,110 It's going to have a left child, left subtree, right subtree. 501 00:28:54,110 --> 00:28:56,360 X is going to be its successor so it's 502 00:28:56,360 --> 00:28:58,640 the leftmost thing in there. 503 00:28:58,640 --> 00:29:06,020 And we still have v with its left child and this pointer. 504 00:29:06,020 --> 00:29:07,110 It's not in the tree. 505 00:29:07,110 --> 00:29:10,250 So if two ox trees, now I want to basically merge these two ox 506 00:29:10,250 --> 00:29:13,880 trees, but also get rid of this stuff. 507 00:29:13,880 --> 00:29:15,350 Just like we did up here actually. 508 00:29:15,350 --> 00:29:18,620 First, I have to destroy this preferred child 509 00:29:18,620 --> 00:29:20,780 and then make a new one, which is v. 510 00:29:20,780 --> 00:29:21,530 So how do I do it? 511 00:29:21,530 --> 00:29:23,960 I just replace the right pointer from w 512 00:29:23,960 --> 00:29:29,480 to be v instead of whatever this thing is that's it. 513 00:29:29,480 --> 00:29:42,110 So say, switch w's preferred child to be v. And what we do 514 00:29:42,110 --> 00:29:51,440 is say w, first we clip off the existing guy, 515 00:29:51,440 --> 00:29:57,110 we say this node's w.rights path parent is now going to be w. 516 00:29:57,110 --> 00:29:59,900 We still want to have some way to get from here back up to w, 517 00:29:59,900 --> 00:30:01,640 just like we did up here. 518 00:30:01,640 --> 00:30:04,530 This code is going to look very similar to these two lines. 519 00:30:04,530 --> 00:30:05,825 We set it's parents to none. 520 00:30:09,300 --> 00:30:13,560 And we set w.right. 521 00:30:13,560 --> 00:30:15,470 Up, here we set it to none. 522 00:30:15,470 --> 00:30:18,230 Now we know it actually needs to be v. 523 00:30:18,230 --> 00:30:19,880 And then we set the reverse pointer 524 00:30:19,880 --> 00:30:26,150 so v's parent is now w and v no longer has a path parent. 525 00:30:31,920 --> 00:30:35,900 So essentially the reverse of these operations. 526 00:30:35,900 --> 00:30:38,450 So we remove this preferred child pointer 527 00:30:38,450 --> 00:30:39,770 and we add this one in. 528 00:30:39,770 --> 00:30:44,840 So the new picture will be, we have w has its left subtree 529 00:30:44,840 --> 00:30:46,250 just like before. 530 00:30:46,250 --> 00:30:49,770 It's right subtree is now v with its left subtree. 531 00:30:49,770 --> 00:30:53,210 And then we also have this other tree hanging out. 532 00:30:53,210 --> 00:30:57,219 Not directly connected except by path parent pointer. 533 00:30:57,219 --> 00:30:59,510 So whereas before, v was linked in with the path parent 534 00:30:59,510 --> 00:31:01,926 pointer, now this thing is linked to in the parent pointer 535 00:31:01,926 --> 00:31:03,680 and sort of the primary connection, 536 00:31:03,680 --> 00:31:07,670 the white connection is direct from w to v. 537 00:31:07,670 --> 00:31:09,470 And that's exactly what corresponds 538 00:31:09,470 --> 00:31:11,730 to clipping off this portion of the preferred path 539 00:31:11,730 --> 00:31:16,330 and concatenating on this portion of the preferred path. 540 00:31:16,330 --> 00:31:17,600 More or less clear? 541 00:31:17,600 --> 00:31:19,450 You can double check this at home 542 00:31:19,450 --> 00:31:23,754 but that's what we need to, do. 543 00:31:23,754 --> 00:31:25,670 To go back and forth between these two worlds. 544 00:31:25,670 --> 00:31:28,969 The represented world and the tree of our world 545 00:31:28,969 --> 00:31:30,010 is doing the right thing. 546 00:31:30,010 --> 00:31:34,620 Again you can check that this path parent is, indeed, 547 00:31:34,620 --> 00:31:35,410 the right thing. 548 00:31:35,410 --> 00:31:37,330 It's essentially saying the parent of x equals 549 00:31:37,330 --> 00:31:39,890 w, which is, indeed, the case. 550 00:31:39,890 --> 00:31:45,640 That left most thing here, its parent is w. 551 00:31:45,640 --> 00:31:51,730 Cool last thing we do is kind of a lame way to say it, 552 00:31:51,730 --> 00:31:55,360 but I want to splay v within its ox tree Now, 553 00:31:55,360 --> 00:31:56,720 v is a child of the root. 554 00:31:56,720 --> 00:32:01,290 So this just means rotate v. So what 555 00:32:01,290 --> 00:32:05,800 it's going to look like is v becomes the root, 556 00:32:05,800 --> 00:32:10,690 it's left child is w, that left child is whatever, 557 00:32:10,690 --> 00:32:12,330 that right child is whatever. 558 00:32:12,330 --> 00:32:15,554 V will still have no right child because v is the deepest 559 00:32:15,554 --> 00:32:16,720 node in it's preferred path. 560 00:32:16,720 --> 00:32:17,890 So there's nothing deeper than it. 561 00:32:17,890 --> 00:32:19,510 There's nothing to the right of v. 562 00:32:19,510 --> 00:32:22,010 So these two triangles go to here. 563 00:32:22,010 --> 00:32:24,520 Of course, there's still the old triangle with x in it, 564 00:32:24,520 --> 00:32:27,500 and it's still going to prefer it's still going to point to w. 565 00:32:30,040 --> 00:32:31,660 But we want v to eventually end up 566 00:32:31,660 --> 00:32:35,860 to be the very, very root so I'd like to make the root again 567 00:32:35,860 --> 00:32:39,450 after I did this concatenation. 568 00:32:39,450 --> 00:32:43,260 And so there you go you can think of this as a second splay 569 00:32:43,260 --> 00:32:50,170 if you want or as a rotation, either way. 570 00:32:50,170 --> 00:32:52,040 And now we're going to loop. 571 00:32:52,040 --> 00:32:54,820 OK, the one thing I didn't make explicit 572 00:32:54,820 --> 00:32:58,870 is that when we do a splay, or when we do a rotation, 573 00:32:58,870 --> 00:33:02,650 you have to carry along the path parent pointer. 574 00:33:02,650 --> 00:33:05,830 So like right now, sorry, in this picture, 575 00:33:05,830 --> 00:33:07,690 w has some path parent pointer because it's 576 00:33:07,690 --> 00:33:09,340 the root of its ox tree. 577 00:33:09,340 --> 00:33:11,399 After we do the rotation, v is the root 578 00:33:11,399 --> 00:33:13,690 and so it's going to have the parent path parent point. 579 00:33:13,690 --> 00:33:18,770 Or you can just define rotate to preserve that information. 580 00:33:18,770 --> 00:33:22,030 So now v has some new path parent and we do the loop. 581 00:33:22,030 --> 00:33:24,650 As long as it is not there's something there, 582 00:33:24,650 --> 00:33:27,700 we're going to splay it stick them together. 583 00:33:27,700 --> 00:33:30,490 Repeat, the number of times we repeat, 584 00:33:30,490 --> 00:33:34,042 is equal to the number of preferred child changes. 585 00:33:34,042 --> 00:33:36,000 So that's how we're going to analyze the thing. 586 00:33:36,000 --> 00:33:41,020 How many times does a child have to change in this world. 587 00:33:41,020 --> 00:33:47,410 OK, clear, more or less that is that's 588 00:33:47,410 --> 00:33:49,630 the hard the hard operation access. 589 00:33:52,960 --> 00:33:56,290 One thing to note is v will have no right child at the end, 590 00:33:56,290 --> 00:33:59,410 and it will be the root of the tree of ox trees. 591 00:33:59,410 --> 00:34:01,240 Why the tree of ox trees? 592 00:34:01,240 --> 00:34:03,490 When we stop, we have no path parent. 593 00:34:03,490 --> 00:34:05,720 That means we are the overall root. 594 00:34:05,720 --> 00:34:06,610 So that's the end. 595 00:34:09,570 --> 00:34:14,830 Cool now let me tell you how to do-- 596 00:34:14,830 --> 00:34:16,710 first, I'll do the queries, and then I'll 597 00:34:16,710 --> 00:34:17,989 do the updates, link-cut. 598 00:34:17,989 --> 00:34:20,590 Cut Make tree, I'm pretty sure, if you all think 599 00:34:20,590 --> 00:34:22,440 you know how did you make tree. 600 00:34:22,440 --> 00:34:24,020 So let's start with find root. 601 00:34:28,530 --> 00:34:36,150 So for find root, first thing we're going to do is access v. 602 00:34:36,150 --> 00:34:42,750 So what that gives us is v, no right child, some left child. 603 00:34:42,750 --> 00:34:47,489 This is v's ox tree, but the roots of the overall tree 604 00:34:47,489 --> 00:34:48,949 is right here. 605 00:34:48,949 --> 00:34:49,530 This is r. 606 00:34:52,060 --> 00:34:54,610 Because, in the end, we know that, 607 00:34:54,610 --> 00:34:58,150 the mean the root ox tree always contains the root 608 00:34:58,150 --> 00:35:02,010 node of the tree, and the access operation makes it also 609 00:35:02,010 --> 00:35:09,400 contain v So what's the highest node in that path from r to v? 610 00:35:09,400 --> 00:35:11,590 Well, it's the left most node in the thing. 611 00:35:11,590 --> 00:35:20,650 So you just block left to find the root r. 612 00:35:20,650 --> 00:35:24,546 And then, we are going to do one more thing, which splay r. 613 00:35:24,546 --> 00:35:26,410 If we didn't splay r, we'd be in trouble 614 00:35:26,410 --> 00:35:28,450 because this is a splay tree. 615 00:35:28,450 --> 00:35:32,360 If you say this r might be extremely deep in the tree. 616 00:35:32,360 --> 00:35:34,510 And so if you just repeatedly said, find root of v, 617 00:35:34,510 --> 00:35:36,730 find v for the same v, you don't want 618 00:35:36,730 --> 00:35:39,940 to have to walk down linear length path every single time. 619 00:35:39,940 --> 00:35:43,870 So we're going to splay it every time we touch the root, 620 00:35:43,870 --> 00:35:47,500 so that very soon r will be near the root of the tree of ox 621 00:35:47,500 --> 00:35:49,520 trees, and so this operation will become fast. 622 00:35:49,520 --> 00:35:52,150 So amortized it will always be order log n. 623 00:35:52,150 --> 00:35:54,970 But we need to do that. 624 00:35:54,970 --> 00:35:57,700 OK that's fine root. 625 00:35:57,700 --> 00:35:59,606 Let's do half aggregate. 626 00:36:05,570 --> 00:36:08,440 Of aggregates basically the same. 627 00:36:08,440 --> 00:36:09,910 Actually, even easier. 628 00:36:09,910 --> 00:36:12,040 First thing we do like all of our operations, 629 00:36:12,040 --> 00:36:16,270 is access v, so we get that picture. 630 00:36:16,270 --> 00:36:18,700 So remember what this corresponds to? 631 00:36:18,700 --> 00:36:26,026 This is an ox tree that represents a path ending in v 632 00:36:26,026 --> 00:36:29,860 So this is in the represented tree. 633 00:36:29,860 --> 00:36:31,840 And the goal of a path aggregate is 634 00:36:31,840 --> 00:36:35,480 to compute the min or the max or to some of those things. 635 00:36:35,480 --> 00:36:37,450 So I basically have this tree that 636 00:36:37,450 --> 00:36:39,970 represents exactly the things I care about, 637 00:36:39,970 --> 00:36:43,780 and I just need to do a sum or a min or a max or whatever. 638 00:36:43,780 --> 00:36:46,390 So easy way to do it is augment all the ox trees 639 00:36:46,390 --> 00:36:48,640 to have subtree size, subtree sums, 640 00:36:48,640 --> 00:36:51,860 or mins or maxes, whatever operations you care about. 641 00:36:51,860 --> 00:37:03,510 And so then it's just a return v.subtree min max, whatever. 642 00:37:08,230 --> 00:37:10,707 You have to have to check when we do link-cuts 643 00:37:10,707 --> 00:37:12,790 that it's easy to maintain augmentation like this, 644 00:37:12,790 --> 00:37:13,930 but it is. 645 00:37:13,930 --> 00:37:17,200 And now this, the subtree aggregations 646 00:37:17,200 --> 00:37:19,030 are relative to your own ox tree. 647 00:37:19,030 --> 00:37:20,741 You don't go deeper. 648 00:37:20,741 --> 00:37:22,240 In fact, there's no way to go deeper 649 00:37:22,240 --> 00:37:24,380 because if you look at the structure, 650 00:37:24,380 --> 00:37:25,540 there's no way to go down. 651 00:37:25,540 --> 00:37:27,100 We store these path parents, but we 652 00:37:27,100 --> 00:37:29,950 can't afford to store path children because a node may 653 00:37:29,950 --> 00:37:32,050 have a zillion path children. 654 00:37:32,050 --> 00:37:34,600 So it's kind of awkward to store them. 655 00:37:34,600 --> 00:37:37,900 we don't have to because this aggregation is just 656 00:37:37,900 --> 00:37:38,956 within the ox tree. 657 00:37:38,956 --> 00:37:40,330 That's exactly what we care about 658 00:37:40,330 --> 00:37:44,120 because it represents that path and nothing more. 659 00:37:44,120 --> 00:37:48,670 So you see, access makes our life pretty darn easy. 660 00:37:48,670 --> 00:37:50,650 Once that path is preferred, we can do whatever 661 00:37:50,650 --> 00:37:51,760 we need to with that path. 662 00:37:51,760 --> 00:37:56,350 We can compute aggregations, the root, anything pretty 663 00:37:56,350 --> 00:37:58,255 much instantly once we have access. 664 00:38:00,790 --> 00:38:04,240 OK, I claim also link and cut are really easy. 665 00:38:08,060 --> 00:38:11,210 So let me show you that. 666 00:38:11,210 --> 00:38:12,230 So let's start with cut. 667 00:38:16,060 --> 00:38:23,320 First thing we do, you guessed it, access v. So 668 00:38:23,320 --> 00:38:24,940 think about this picture a little bit. 669 00:38:24,940 --> 00:38:28,900 So we have v, have this stuff. 670 00:38:28,900 --> 00:38:31,520 What this corresponds to, this is the ox tree 671 00:38:31,520 --> 00:38:33,250 in the represented tree. 672 00:38:33,250 --> 00:38:37,090 This is a path from the root to v. 673 00:38:37,090 --> 00:38:39,280 And our goal in the cut operation 674 00:38:39,280 --> 00:38:42,700 is to separate v from its parent in the represented tree. 675 00:38:42,700 --> 00:38:46,840 So we want to remove this edge above v. That basically 676 00:38:46,840 --> 00:38:48,970 corresponds to this edge. 677 00:38:48,970 --> 00:38:52,210 Connection from v to all the things less deep than it. 678 00:38:52,210 --> 00:38:53,530 So this is the preferred path. 679 00:38:53,530 --> 00:38:57,040 Of course, in reality, there is some subtree down here, 680 00:38:57,040 --> 00:38:59,990 and that's going to correspond to things that are linked here 681 00:38:59,990 --> 00:39:02,030 by path parent pointers. 682 00:39:02,030 --> 00:39:05,410 So they'll come along for the ride, because what they know 683 00:39:05,410 --> 00:39:09,310 is they're attached to v. And so all we need to do 684 00:39:09,310 --> 00:39:11,650 is delete this edge and we're done. 685 00:39:11,650 --> 00:39:17,450 It's kind of crazy, but it works. 686 00:39:17,450 --> 00:39:27,550 So what we do, say, v left the parent is none. 687 00:39:27,550 --> 00:39:31,870 The left is none. 688 00:39:31,870 --> 00:39:32,860 That's it. 689 00:39:32,860 --> 00:39:33,830 Gone. 690 00:39:33,830 --> 00:39:36,100 That edge has disappeared. 691 00:39:36,100 --> 00:39:40,405 What will be left with is v all by itself. 692 00:39:40,405 --> 00:39:42,970 / Has no left child, no right child. 693 00:39:42,970 --> 00:39:48,070 It still has some things that link into it via path parent 694 00:39:48,070 --> 00:39:49,940 pointers. 695 00:39:49,940 --> 00:39:56,500 But v is alone in its ox tree after you do a cut. 696 00:39:56,500 --> 00:39:59,860 This thing will now live in a separate world. 697 00:39:59,860 --> 00:40:03,760 In particular, this node becomes the new root 698 00:40:03,760 --> 00:40:06,860 of the tree of ox trees for this tree. 699 00:40:06,860 --> 00:40:08,770 after we do the cut, there's two trees. 700 00:40:08,770 --> 00:40:10,150 So there's two trees of ox trees. 701 00:40:10,150 --> 00:40:12,250 There's the one with v, v will remain the root 702 00:40:12,250 --> 00:40:14,200 of its tree of ox trees. 703 00:40:14,200 --> 00:40:17,950 And the other one, this thing called x, 704 00:40:17,950 --> 00:40:21,720 becomes its own root of its own tree of ox trees. 705 00:40:21,720 --> 00:40:23,130 So there's nothing else to do. 706 00:40:23,130 --> 00:40:25,270 It doesn't need a parent pointer because it's not 707 00:40:25,270 --> 00:40:28,230 linked to anything above it. 708 00:40:28,230 --> 00:40:30,910 The end. 709 00:40:30,910 --> 00:40:33,740 OK, I corresponds to some node up here. 710 00:40:33,740 --> 00:40:34,840 Kind of the median node. 711 00:40:39,130 --> 00:40:40,550 So there you go. 712 00:40:40,550 --> 00:40:41,570 That's a cut. 713 00:40:41,570 --> 00:40:43,832 It's like super short code. 714 00:40:43,832 --> 00:40:45,290 You have to stare at it for a while 715 00:40:45,290 --> 00:40:49,940 and make sure it does all the right things, but it does. 716 00:40:49,940 --> 00:40:51,240 How about a link? 717 00:40:51,240 --> 00:40:54,999 Well first thing we do on a link, is access v and access w. 718 00:40:54,999 --> 00:40:56,540 These don't interfere with each other 719 00:40:56,540 --> 00:40:59,170 because precondition is that v and w are 720 00:40:59,170 --> 00:41:01,360 in different trees of ox trees. 721 00:41:01,360 --> 00:41:04,520 They're indifferent represented trees. 722 00:41:04,520 --> 00:41:06,170 So they're completely independent. 723 00:41:06,170 --> 00:41:08,150 The result will be that we have-- 724 00:41:15,030 --> 00:41:18,790 should be consistent --so ox trees are on the left. 725 00:41:18,790 --> 00:41:22,690 We're going to have w, is going to have a left thing. 726 00:41:22,690 --> 00:41:27,010 We're going to have v claim all by itself because remember 727 00:41:27,010 --> 00:41:28,540 what a link does? 728 00:41:28,540 --> 00:41:31,390 It's right here, v is assumed to be a root node. 729 00:41:31,390 --> 00:41:34,030 So if you do an access on the root node, 730 00:41:34,030 --> 00:41:36,840 then the path from the root to v is a very short path. 731 00:41:36,840 --> 00:41:38,630 It is just v itself. 732 00:41:38,630 --> 00:41:40,330 So the ox tree containing v, will just 733 00:41:40,330 --> 00:41:46,060 be v itself when you do x as v. Yeah, so 734 00:41:46,060 --> 00:41:50,005 this is the picture in represented space. 735 00:41:50,005 --> 00:41:51,880 And so we access v, we're going to have this. 736 00:41:51,880 --> 00:41:53,790 Of course, there's stuff pointing into it. 737 00:41:53,790 --> 00:41:56,770 We're at access w, so it's going to look like this. 738 00:41:56,770 --> 00:42:00,244 And then this path is going to be what's over here. 739 00:42:00,244 --> 00:42:01,660 And there's, of course, more stuff 740 00:42:01,660 --> 00:42:03,880 linked from below into those. 741 00:42:03,880 --> 00:42:08,050 Our goal is to add this edge between v and w, which 742 00:42:08,050 --> 00:42:10,660 corresponds to adding this change. 743 00:42:15,050 --> 00:42:18,540 So that's what we're going to do. 744 00:42:18,540 --> 00:42:20,278 V.left left equals w. 745 00:42:23,086 --> 00:42:29,920 W.parent equals v. 746 00:42:29,920 --> 00:42:34,210 If you want, you could instead make v the right child of w. 747 00:42:34,210 --> 00:42:35,740 And that looks much more sane. 748 00:42:35,740 --> 00:42:38,390 I like it this way because it looks kind of insane. 749 00:42:38,390 --> 00:42:39,929 This is not unbalanced or anything. 750 00:42:39,929 --> 00:42:42,220 But splay trees will fix it so you don't have to worry. 751 00:42:42,220 --> 00:42:45,490 This is the carefree approach to data structuring. 752 00:42:45,490 --> 00:42:47,830 And you just leave it to the analysis to make sure. 753 00:42:47,830 --> 00:42:52,060 Everything here is going to be log n amortized. 754 00:42:52,060 --> 00:42:56,170 But you can check this is doing the right thing, because v 755 00:42:56,170 --> 00:42:57,780 is deeper than w, right? 756 00:42:57,780 --> 00:43:01,250 So we had this path from the root over here to w. 757 00:43:01,250 --> 00:43:03,884 We're extending the path by one node, v, 758 00:43:03,884 --> 00:43:05,800 and so v should be to the right of everything. 759 00:43:05,800 --> 00:43:08,140 So either it goes that here is that right child 760 00:43:08,140 --> 00:43:11,110 w that would also work, or would make it the parent of w 761 00:43:11,110 --> 00:43:13,280 on the right that works. 762 00:43:13,280 --> 00:43:16,750 It's in the correct order, binary search tree order. 763 00:43:16,750 --> 00:43:18,220 OK? 764 00:43:18,220 --> 00:43:20,475 So you see length and links and cuts are easy. 765 00:43:20,475 --> 00:43:21,850 In fact, the most complicated was 766 00:43:21,850 --> 00:43:25,690 find root where we had to do a walk and splay, 767 00:43:25,690 --> 00:43:28,360 but basically, everything reduces to access. 768 00:43:28,360 --> 00:43:30,910 If access is fast, all these operations 769 00:43:30,910 --> 00:43:33,970 will be fast because they spend essentially constant time 770 00:43:33,970 --> 00:43:36,365 plus a constant number of accesses. 771 00:43:36,365 --> 00:43:37,240 Except for find root. 772 00:43:37,240 --> 00:43:38,290 It also doesn't splay. 773 00:43:38,290 --> 00:43:40,373 But we're going to show displays are efficient as, 774 00:43:40,373 --> 00:43:44,010 well as part of access, because access does a ton of splays. 775 00:43:44,010 --> 00:43:45,550 So this is log n amortize, surely 776 00:43:45,550 --> 00:43:47,290 one splay is log n amortized. 777 00:43:47,290 --> 00:43:50,300 And indeed, that will be the case. 778 00:43:50,300 --> 00:43:53,800 AUDIENCE: Splay as access. 779 00:43:53,800 --> 00:43:56,680 PROFESSOR: Here, I'm treating splaying not as an access. 780 00:43:56,680 --> 00:44:00,569 So I'm going to define access to mean calling this function. 781 00:44:00,569 --> 00:44:01,976 AUDIENCE: [INAUDIBLE]. 782 00:44:07,140 --> 00:44:10,250 PROFESSOR: OK so over here, access first splays v 783 00:44:10,250 --> 00:44:11,470 and displays various things. 784 00:44:11,470 --> 00:44:13,914 It might not splay r. 785 00:44:13,914 --> 00:44:17,650 AUDIENCE: No, I'm saying, do you call access r [INAUDIBLE]? 786 00:44:17,650 --> 00:44:19,270 PROFESSOR: Oh good. 787 00:44:19,270 --> 00:44:21,160 That might simplify my analysis. 788 00:44:21,160 --> 00:44:25,540 I'll just change this line to access r. 789 00:44:25,540 --> 00:44:28,390 Good, why not? 790 00:44:31,060 --> 00:44:32,980 Yeah, that seems like a good way. 791 00:44:36,400 --> 00:44:38,350 OK, I think you could do that. 792 00:44:38,350 --> 00:44:41,410 It might simplify, conceptually, what's going on. 793 00:44:41,410 --> 00:44:45,410 The one thing I find annoying about it's just-- 794 00:44:45,410 --> 00:44:47,050 it's an aesthetic, let's say. 795 00:44:47,050 --> 00:44:50,260 So here, I was talking about the last access. 796 00:44:50,260 --> 00:44:53,800 And if you define lost access to mean access, that's fine. 797 00:44:53,800 --> 00:44:56,170 But also another intuitive notion of the last access, 798 00:44:56,170 --> 00:44:59,650 is the last time it was given to any of these functions cut link 799 00:44:59,650 --> 00:45:01,520 find root path aggregate. 800 00:45:01,520 --> 00:45:03,942 And so r is not really given to the function. 801 00:45:03,942 --> 00:45:05,650 Of course, it's the output of find roots, 802 00:45:05,650 --> 00:45:07,840 so maybe you think of that as an access. 803 00:45:07,840 --> 00:45:10,270 You could say find root is accessing the root. 804 00:45:10,270 --> 00:45:13,680 Either way, this should work either way, 805 00:45:13,680 --> 00:45:15,660 but I think I like that. 806 00:45:15,660 --> 00:45:19,190 You just have to redefine things a little. 807 00:45:19,190 --> 00:45:21,250 OK, let's do some analysis. 808 00:45:21,250 --> 00:45:22,990 This is the data structure. 809 00:45:22,990 --> 00:45:25,280 Algorithms are all up there in they're gory detail. 810 00:45:25,280 --> 00:45:25,780 This is. 811 00:45:25,780 --> 00:45:26,260 Of course. 812 00:45:26,260 --> 00:45:26,760 goriest. 813 00:45:34,604 --> 00:45:40,130 I can now erase the, API. 814 00:45:53,780 --> 00:45:57,290 Makes me think of Google versus Oracle. 815 00:45:57,290 --> 00:45:59,180 And then following that case? 816 00:45:59,180 --> 00:46:02,278 Yeah, it's interesting. 817 00:46:06,190 --> 00:46:23,590 OK pretty clear this implementation 818 00:46:23,590 --> 00:46:26,360 is much more significant than the API, but anyway. 819 00:46:26,360 --> 00:46:28,120 If 820 00:46:28,120 --> 00:46:30,190 First goal is to prove log squared. 821 00:46:30,190 --> 00:46:31,840 This is just like a warm up. 822 00:46:31,840 --> 00:46:33,622 This is actually trivial at this point. 823 00:46:33,622 --> 00:46:35,830 We've done all the work to do a lot of squared bound. 824 00:46:35,830 --> 00:46:37,454 In fact, you just replace the slay tree 825 00:46:37,454 --> 00:46:39,670 with a red-black tree, and you know 826 00:46:39,670 --> 00:46:44,380 that each of these operations is Log n. 827 00:46:44,380 --> 00:46:47,140 All displays that we do, I mean, you can do essentially 828 00:46:47,140 --> 00:46:49,754 like a splay in a balance binary [INAUDIBLE] tree, 829 00:46:49,754 --> 00:46:51,170 you can still move it to the root. 830 00:46:51,170 --> 00:46:54,070 You can still maintain it temporarily and maintain 831 00:46:54,070 --> 00:46:55,237 the height is order log n. 832 00:46:55,237 --> 00:46:56,320 That's one way to view it. 833 00:46:56,320 --> 00:46:58,652 Or you can observe the splay tree analysis 834 00:46:58,652 --> 00:47:00,610 that gives you log n, which we haven't actually 835 00:47:00,610 --> 00:47:02,140 covered in this class. 836 00:47:02,140 --> 00:47:03,520 Still applies in this scenario. 837 00:47:03,520 --> 00:47:05,103 Even though it's not one splay a tree. 838 00:47:05,103 --> 00:47:06,490 It's a bunch of trees. 839 00:47:06,490 --> 00:47:09,220 You can show each of the splays is order log n. 840 00:47:09,220 --> 00:47:13,900 So what that gives you is that-- 841 00:47:13,900 --> 00:47:18,285 so we have lets just say it's order log n amortized 842 00:47:18,285 --> 00:47:22,680 per splay, a few splay trees or use regular balancer 843 00:47:22,680 --> 00:47:24,690 trees is definitely log n. 844 00:47:24,690 --> 00:47:33,220 So then if we do m operations, it's going to cost --we're not 845 00:47:33,220 --> 00:47:35,020 actually going to be done-- 846 00:47:35,020 --> 00:47:41,680 order log n times m plus total number 847 00:47:41,680 --> 00:47:43,045 of preferred child changes. 848 00:47:54,400 --> 00:47:58,150 This bound should be clear, because every operation reduces 849 00:47:58,150 --> 00:48:02,170 to accesses plus constant amount of work. 850 00:48:02,170 --> 00:48:07,070 Maybe one more splay a splay is just another log n. 851 00:48:07,070 --> 00:48:15,100 And the total number of preferred child changes 852 00:48:15,100 --> 00:48:16,920 comes from this access thing. 853 00:48:16,920 --> 00:48:20,609 We're doing one splay per preferred child change. 854 00:48:20,609 --> 00:48:22,150 So that thing is reasonable, you just 855 00:48:22,150 --> 00:48:24,640 take it, multiply by log n, we're done. 856 00:48:24,640 --> 00:48:28,810 So the remaining thing is, at this point, just claim. 857 00:48:28,810 --> 00:48:34,700 Total number of preferred trial changes is order m log n. 858 00:48:34,700 --> 00:48:38,470 So if you take this whole thing, divide by m, 859 00:48:38,470 --> 00:48:41,740 you get log squared amortize. 860 00:48:41,740 --> 00:48:44,380 So that sounds kind of lame, log square 861 00:48:44,380 --> 00:48:46,847 is not such a good bound, but it's a warm up. 862 00:48:46,847 --> 00:48:48,430 In fact, we need to prove this anyway. 863 00:48:48,430 --> 00:48:50,090 We need this for the log n analysis. 864 00:48:50,090 --> 00:48:51,640 So first thing I'm going to do is 865 00:48:51,640 --> 00:48:56,020 prove total number of preferred child changes is log squared. 866 00:48:56,020 --> 00:48:59,510 Before I do that, I need heavy-light decomposition. 867 00:48:59,510 --> 00:49:02,140 So to prove, this we're going to use heavy-light decomposition. 868 00:49:02,140 --> 00:49:04,223 And this I think, is where things get pretty cool. 869 00:49:22,440 --> 00:49:25,320 So heavy-light decomposition, this 870 00:49:25,320 --> 00:49:30,280 is another way to decompose a tree into paths. 871 00:49:33,510 --> 00:49:35,250 So heavy-light decomposition is, again, 872 00:49:35,250 --> 00:49:38,580 going to apply to the represented tree. 873 00:49:38,580 --> 00:49:39,630 Not the tree of ox trees. 874 00:49:39,630 --> 00:49:42,930 It's like an intrinsic thing. 875 00:49:42,930 --> 00:49:47,340 It's very simple we define the size of the node 876 00:49:47,340 --> 00:49:50,340 to be the number of nodes in that subtree. 877 00:49:50,340 --> 00:49:52,740 We've done this many times, I think. 878 00:49:58,140 --> 00:50:04,560 And then, we're going to call an edge from v 879 00:50:04,560 --> 00:50:14,150 to its parent heavy or light. 880 00:50:14,150 --> 00:50:23,020 It's heavy if the size of v is more than half 881 00:50:23,020 --> 00:50:24,375 of the size of its parent. 882 00:50:32,164 --> 00:50:33,580 And, otherwise, it's called light. 883 00:50:41,570 --> 00:50:45,640 OK, so we have parent and sub child v 884 00:50:45,640 --> 00:50:47,990 has loads of other children. 885 00:50:47,990 --> 00:50:51,080 I just want to know, is the heaviest of all your children? 886 00:50:51,080 --> 00:50:52,910 That's one way to define it. 887 00:50:52,910 --> 00:50:55,010 But, in, particular is a bigger than half 888 00:50:55,010 --> 00:50:56,859 of the total weight of p? 889 00:50:56,859 --> 00:50:58,400 So there might not be any heavy child 890 00:50:58,400 --> 00:50:59,608 according to this definition. 891 00:50:59,608 --> 00:51:01,700 Maybe it's nicely evenly balanced. 892 00:51:01,700 --> 00:51:03,090 Everybody's got a third. 893 00:51:03,090 --> 00:51:05,540 But if somebody has got bigger than 1/2, I call it heavy. 894 00:51:05,540 --> 00:51:06,620 Everybody else is light. 895 00:51:06,620 --> 00:51:10,490 So there's going to be, at most, one heavy edge from every node. 896 00:51:10,490 --> 00:51:14,590 Therefore, heavy edges decompose your world into path's. 897 00:51:14,590 --> 00:51:17,300 Heavy paths decompose the tree. 898 00:51:28,730 --> 00:51:34,100 Nodes, every node lives in some heavy path. 899 00:51:34,100 --> 00:51:38,840 It may be node has no heavy childs, but, at most, one. 900 00:51:38,840 --> 00:51:43,010 This may seem kind of silly, but in fact, because your maybe 901 00:51:43,010 --> 00:51:43,880 all edges are light. 902 00:51:43,880 --> 00:51:45,640 This might not do anything, every node 903 00:51:45,640 --> 00:51:49,160 is in its own path, that's actually a really good case, 904 00:51:49,160 --> 00:51:51,080 light edges are good. 905 00:51:51,080 --> 00:51:51,830 Why are they good? 906 00:51:51,830 --> 00:51:55,130 Because then the size of v is at most half the size 907 00:51:55,130 --> 00:51:56,190 of its parent. 908 00:51:56,190 --> 00:51:58,640 I mean, every time you follow a light edge, 909 00:51:58,640 --> 00:52:01,350 the size of your subtree went down by a factor of 2. 910 00:52:01,350 --> 00:52:02,930 How many times is going to happen? 911 00:52:02,930 --> 00:52:04,310 Log n times. 912 00:52:04,310 --> 00:52:07,430 Start with everything at the root, as you walk down, 913 00:52:07,430 --> 00:52:09,980 if you're decreasing your side effect or two every time, 914 00:52:09,980 --> 00:52:12,140 you can only follow log . 915 00:52:12,140 --> 00:52:13,740 Light edges. 916 00:52:13,740 --> 00:52:15,810 This is what we call the light depth of a node. 917 00:52:22,440 --> 00:52:29,545 This is the number of light edges on a root to the path. 918 00:52:38,070 --> 00:52:42,374 And it is always, at most, log n. 919 00:52:42,374 --> 00:52:44,040 Now, remember heavy edges could be huge. 920 00:52:44,040 --> 00:52:46,380 Maybe you follow, maybe your tree is a path. 921 00:52:46,380 --> 00:52:47,940 Then every edge is heavy. 922 00:52:47,940 --> 00:52:53,580 And you n of them to get from the root of v. 923 00:52:53,580 --> 00:52:55,480 So we can't bound the number of heavy edges. 924 00:52:55,480 --> 00:52:59,760 But the number of light we can bound as log n. 925 00:52:59,760 --> 00:53:04,520 This is where heavy light to composition is useful. 926 00:53:04,520 --> 00:53:06,324 So you've got preferred path composition. 927 00:53:06,324 --> 00:53:08,490 Our Or data structure, we're not going to change it. 928 00:53:08,490 --> 00:53:09,970 It's still following the preferred path 929 00:53:09,970 --> 00:53:10,720 the decomposition. 930 00:53:10,720 --> 00:53:13,350 But our analysis is going to think about which edges 931 00:53:13,350 --> 00:53:16,830 are heavy and which are light. 932 00:53:16,830 --> 00:53:20,310 In general, an edge can have four different states. 933 00:53:20,310 --> 00:53:22,710 It can be preferred or not preferred. 934 00:53:22,710 --> 00:53:25,110 And it can be preferred or not preferred, 935 00:53:25,110 --> 00:53:27,020 it could be heavy or light. 936 00:53:27,020 --> 00:53:29,050 All four of those combinations are possible, 937 00:53:29,050 --> 00:53:31,560 because one of them has to do with the access sequence, 938 00:53:31,560 --> 00:53:34,026 the other has to do with the structure of the tree. 939 00:53:34,026 --> 00:53:35,900 These are basically orthogonal to each other. 940 00:53:38,588 --> 00:53:44,610 OK, so let's maybe go here. 941 00:54:09,990 --> 00:54:12,890 So next thing I'm going to do is use heavy light decomposition 942 00:54:12,890 --> 00:54:16,250 to analyze total number of preferred child changes, 943 00:54:16,250 --> 00:54:18,470 by looking at not only whether an edge is preferred 944 00:54:18,470 --> 00:54:20,600 or not, but whether it is heavy or light. 945 00:54:23,960 --> 00:54:32,775 We're going to get an order m log n bound on preferred child 946 00:54:32,775 --> 00:54:33,275 changes. 947 00:54:40,970 --> 00:54:42,860 So here's the big idea. 948 00:55:29,970 --> 00:55:33,990 In order for a preferred child to change, 949 00:55:33,990 --> 00:55:36,360 I mean when you change for a child of one node 950 00:55:36,360 --> 00:55:39,870 from this to this, I'm going to think of this edge 951 00:55:39,870 --> 00:55:42,270 as being destroyed from its preferredness, 952 00:55:42,270 --> 00:55:46,520 and this one is being created in it's preferredness. 953 00:55:46,520 --> 00:55:52,140 OK, so of course, if we could count preferred edge equations, 954 00:55:52,140 --> 00:55:56,940 that would be basically the same as preferred child changes. 955 00:55:56,940 --> 00:56:00,900 Or we could count preferred edge destructions, 956 00:56:00,900 --> 00:56:04,030 that would be basically, the same as the number of changes. 957 00:56:04,030 --> 00:56:05,610 OK, so that's the idea. 958 00:56:05,610 --> 00:56:08,220 If you ignore this part, or look at pilferage equations 959 00:56:08,220 --> 00:56:09,480 or prefer it is destructions. 960 00:56:09,480 --> 00:56:11,370 But then I also care about whether that edge 961 00:56:11,370 --> 00:56:13,890 is light or heavy. 962 00:56:13,890 --> 00:56:16,530 So it turns out for the light edges, 963 00:56:16,530 --> 00:56:19,527 it's going to be easier to talk about the creations 964 00:56:19,527 --> 00:56:20,610 or to bound the creations. 965 00:56:20,610 --> 00:56:22,310 For heavy edges is going to be easier 966 00:56:22,310 --> 00:56:24,360 to bound the destructions. 967 00:56:24,360 --> 00:56:26,910 If I do both of those and add them up, that in total 968 00:56:26,910 --> 00:56:30,330 is, basically, the number of preferred edge changes 969 00:56:30,330 --> 00:56:32,460 according to whether there is light or heavy. 970 00:56:32,460 --> 00:56:35,200 You need to add in a little bit more because 971 00:56:35,200 --> 00:56:38,160 and edge might get created but never destroyed. 972 00:56:38,160 --> 00:56:41,310 And if it's heavy, then it won't get counted here. 973 00:56:41,310 --> 00:56:43,290 Or an edge might get destroyed because it 974 00:56:43,290 --> 00:56:45,600 exists originally, never got created 975 00:56:45,600 --> 00:56:47,309 but it got destroyed over the operations. 976 00:56:47,309 --> 00:56:49,558 And if it was light, then it wouldn't be counted here. 977 00:56:49,558 --> 00:56:51,480 So just add on n plus 1 for all the edges 978 00:56:51,480 --> 00:56:53,100 might get a bonus point. 979 00:56:53,100 --> 00:56:56,260 But, otherwise, this will bound it, 980 00:56:56,260 --> 00:56:58,345 it's going to look at light edge creations-- 981 00:56:58,345 --> 00:57:01,800 creations, light preferred edge creations, heavy preferred edge 982 00:57:01,800 --> 00:57:02,954 distructions. 983 00:57:02,954 --> 00:57:05,370 And it can be destroyed because it becomes no longer heavy 984 00:57:05,370 --> 00:57:06,990 or no longer preferred. 985 00:57:06,990 --> 00:57:09,600 And it can be created because it becomes light 986 00:57:09,600 --> 00:57:12,810 or it becomes preferred and was already the other one. 987 00:57:12,810 --> 00:57:14,310 OK, so all we need to do is think 988 00:57:14,310 --> 00:57:18,510 about, in all these operations, access link-cut, just 989 00:57:18,510 --> 00:57:19,230 the updates. 990 00:57:19,230 --> 00:57:21,720 So access link/cut. 991 00:57:21,720 --> 00:57:23,850 How can this change? 992 00:57:23,850 --> 00:57:24,975 So let's start with access. 993 00:57:30,180 --> 00:57:33,060 So access. 994 00:57:33,060 --> 00:57:33,690 The hard one. 995 00:57:37,620 --> 00:57:39,820 Well, there's all this implementation, 996 00:57:39,820 --> 00:57:41,730 which is dealing with the tree of ox trees, 997 00:57:41,730 --> 00:57:44,100 but really, an access does a very simple thing. 998 00:57:44,100 --> 00:57:47,460 It makes the path from the root to be preferred. 999 00:57:47,460 --> 00:57:48,790 That's its goal. 1000 00:57:48,790 --> 00:57:52,920 So there's the root, it's to v, this becomes preferred 1001 00:57:52,920 --> 00:57:54,630 whether it was before or not. 1002 00:57:54,630 --> 00:57:57,300 Some of it was before some of it wasn't. 1003 00:57:57,300 --> 00:58:00,702 So some of these might be on newly preferred. 1004 00:58:05,630 --> 00:58:07,820 It does not change which edges are heavy or light. 1005 00:58:07,820 --> 00:58:09,350 It does not change the structure of the tree 1006 00:58:09,350 --> 00:58:10,266 when you do an access. 1007 00:58:10,266 --> 00:58:12,740 Only link/cut changed the structure of the tree. 1008 00:58:12,740 --> 00:58:16,010 So it makes some of these edges preferred. 1009 00:58:16,010 --> 00:58:19,070 What that means, of course, is that some other edges 1010 00:58:19,070 --> 00:58:21,770 used to be preferred and are no longer preferred. 1011 00:58:21,770 --> 00:58:24,510 Those are the preferred child changes. 1012 00:58:24,510 --> 00:58:27,140 So if we look at this, first concern 1013 00:58:27,140 --> 00:58:29,620 is that we're creating new preferred edges, 1014 00:58:29,620 --> 00:58:33,074 so maybe we create some new light preferred edges. 1015 00:58:33,074 --> 00:58:34,490 How many new light preferred edges 1016 00:58:34,490 --> 00:58:38,250 could we create along this path? 1017 00:58:38,250 --> 00:58:39,110 Most log n. 1018 00:58:39,110 --> 00:58:43,380 Whatever the light depth of v is as an upper bound. 1019 00:58:43,380 --> 00:58:52,490 So make, at most, log and, like preferred edges, 1020 00:58:52,490 --> 00:58:56,420 because they all live on a single path. 1021 00:58:56,420 --> 00:58:58,430 And it would be really hard to bound how many 1022 00:58:58,430 --> 00:59:01,050 heavy preferred edges we make. 1023 00:59:01,050 --> 00:59:02,050 But we don't have to. 1024 00:59:02,050 --> 00:59:04,460 We don't have to worry about heavy preferred edges being 1025 00:59:04,460 --> 00:59:05,510 destroyed. 1026 00:59:05,510 --> 00:59:07,310 Now, those edges could be these ones. 1027 00:59:07,310 --> 00:59:09,740 These edges used to be preferred, now they're not. 1028 00:59:09,740 --> 00:59:13,610 If they were heavy, then I have to pay for them. 1029 00:59:13,610 --> 00:59:17,420 But the number of these edges is equal to, 1030 00:59:17,420 --> 00:59:19,310 or is at most, the number of these edges. 1031 00:59:19,310 --> 00:59:21,890 I mean, if this edge was heavy, every node 1032 00:59:21,890 --> 00:59:23,960 has only one heavy down pointer. 1033 00:59:23,960 --> 00:59:27,280 So if this edge is heavy hanging off, then this one is light. 1034 00:59:27,280 --> 00:59:29,880 We know there's only log n light edges here. 1035 00:59:29,880 --> 00:59:31,520 So the number of heavy edges coming off 1036 00:59:31,520 --> 00:59:35,370 here can also be most log n, 1037 00:59:35,370 --> 00:59:43,740 So destroy, at most, log n heavy preferred edges. 1038 00:59:47,120 --> 00:59:51,800 Yeah In some sense, we don't even really 1039 00:59:51,800 --> 00:59:55,040 are about the word preferred here. 1040 00:59:55,040 --> 00:59:57,900 But, of course, we're not making them, light so anyway. 1041 01:00:01,324 --> 01:00:02,212 Is that clear? 1042 01:00:02,212 --> 01:00:04,670 Now, there's actually one more edge that could change which 1043 01:00:04,670 --> 01:00:07,880 is, there used to be a preferred edge from v, now there isn't. 1044 01:00:07,880 --> 01:00:11,220 We destroyed that in the very beginning of the operation. 1045 01:00:11,220 --> 01:00:15,650 So maybe plus 1 that might have destroyed one more heavy edge. 1046 01:00:15,650 --> 01:00:19,940 But overall order log n. 1047 01:00:19,940 --> 01:00:22,745 So, actually, really easy to analyze access. 1048 01:00:26,100 --> 01:00:27,210 Any questions about that? 1049 01:00:42,500 --> 01:00:50,000 OK, link/cut not much to say here. 1050 01:00:50,000 --> 01:00:53,600 Yeah, so link/cut don't really change what's preferred. 1051 01:00:53,600 --> 01:00:56,570 I'm analyzing-- I'm going to think about what link 1052 01:00:56,570 --> 01:00:58,310 does after it accesses v and w. 1053 01:00:58,310 --> 01:01:00,710 Because access we've already analyzed. 1054 01:01:00,710 --> 01:01:04,730 So link is just these two operations 1055 01:01:04,730 --> 01:01:06,540 which add a single pointer. 1056 01:01:06,540 --> 01:01:10,760 So if you look at what that's doing in the represented tree, 1057 01:01:10,760 --> 01:01:14,330 which was v was the route and we made 1058 01:01:14,330 --> 01:01:22,490 it to be a new child w, which lived in some tree over here. 1059 01:01:22,490 --> 01:01:24,365 That's in the represented tree, what happens. 1060 01:01:28,470 --> 01:01:34,100 What happens is that w gets heavier. 1061 01:01:34,100 --> 01:01:36,680 I guess also this get's heavier. 1062 01:01:36,680 --> 01:01:41,180 All the nodes on this route to w path get heavier. 1063 01:01:41,180 --> 01:01:44,270 That's all that happens in terms of heavy, light. 1064 01:01:44,270 --> 01:01:45,890 Preferred paths don't change. 1065 01:01:45,890 --> 01:01:49,870 It's just about heavy and light changing. 1066 01:01:49,870 --> 01:01:52,850 OK, in fact, this will be a preferred path 1067 01:01:52,850 --> 01:01:56,060 from the root to v because we just accessed those guys. 1068 01:02:02,640 --> 01:02:06,670 So we're heavying edges, which means you might create 1069 01:02:06,670 --> 01:02:09,010 new heavy preferred edges. 1070 01:02:09,010 --> 01:02:12,760 But we don't care about heavy preferred edges being created. 1071 01:02:12,760 --> 01:02:16,580 We only care about them being destroyed. 1072 01:02:16,580 --> 01:02:18,010 So has anything changed? 1073 01:02:18,010 --> 01:02:22,232 Well, there might have been a heavy edge hanging off of here. 1074 01:02:22,232 --> 01:02:22,940 Is that possible? 1075 01:02:26,550 --> 01:02:29,640 Yeah, so this might turn light, because this one 1076 01:02:29,640 --> 01:02:31,340 became heavier. 1077 01:02:31,340 --> 01:02:33,090 So this edge might become light, which 1078 01:02:33,090 --> 01:02:36,180 means we might have potentially lost-- 1079 01:02:36,180 --> 01:02:38,430 this could have been preferred before. 1080 01:02:38,430 --> 01:02:40,722 It wasn't preferred, so who cares? 1081 01:02:40,722 --> 01:02:42,180 If we've already done the accesses, 1082 01:02:42,180 --> 01:02:43,830 the edges are already not preferred. 1083 01:02:43,830 --> 01:02:45,032 So not a big deal. 1084 01:02:45,032 --> 01:02:45,990 So can anything happen? 1085 01:02:45,990 --> 01:02:48,839 I think not. 1086 01:02:48,839 --> 01:02:50,880 Some of the edges on the path might become heavy, 1087 01:02:50,880 --> 01:02:53,160 but we don't care because they are preferred. 1088 01:02:53,160 --> 01:02:55,260 Some of the edges off the path might become light, 1089 01:02:55,260 --> 01:02:57,260 but we don't care because they're not preferred. 1090 01:02:57,260 --> 01:02:58,680 Done. 1091 01:02:58,680 --> 01:03:04,610 So this actually costs zero in just analyzing number 1092 01:03:04,610 --> 01:03:05,860 of preferred child changes. 1093 01:03:05,860 --> 01:03:09,210 Cuts, not quite so simple. 1094 01:03:09,210 --> 01:03:13,450 When we do a cut, we're lightning stuff. 1095 01:03:16,530 --> 01:03:19,550 The path from the root to v in the represented tree, 1096 01:03:19,550 --> 01:03:23,580 when we line up there, becomes lighter, 1097 01:03:23,580 --> 01:03:28,290 because we cut off that whole subtree containing v. 1098 01:03:28,290 --> 01:03:33,210 So we might create light preferred edges on that path. 1099 01:03:33,210 --> 01:03:35,470 And that's something we actually want to count. 1100 01:03:35,470 --> 01:03:37,710 we count number of light preferred edges created. 1101 01:03:37,710 --> 01:03:43,294 But, again, they're on a path so it's, at most, log n 1102 01:03:43,294 --> 01:03:50,560 Most log n light preferred edges created. 1103 01:03:50,560 --> 01:03:52,560 We don't care about edges hanging off that path 1104 01:03:52,560 --> 01:03:54,143 because they're not preferred anymore, 1105 01:03:54,143 --> 01:03:57,299 so it's nothing to talk about. 1106 01:03:57,299 --> 01:03:57,840 So that's it. 1107 01:03:57,840 --> 01:04:01,701 That proves m log n preferred child changes. 1108 01:04:01,701 --> 01:04:04,200 It's amortized because we're doing this creation/destruction 1109 01:04:04,200 --> 01:04:05,370 business. 1110 01:04:05,370 --> 01:04:08,720 This thing is worst case log n per operation, this quantity. 1111 01:04:08,720 --> 01:04:10,890 But when you sum it up, then you actually 1112 01:04:10,890 --> 01:04:12,880 get about the number of preferred child changes 1113 01:04:12,880 --> 01:04:13,380 overall. 1114 01:04:19,800 --> 01:04:22,770 So if you plug that into this bound, 1115 01:04:22,770 --> 01:04:25,020 we get a log squared m bound. 1116 01:04:25,020 --> 01:04:28,450 Big deal. 1117 01:04:28,450 --> 01:04:30,030 But with a little bit more work, we 1118 01:04:30,030 --> 01:04:31,920 can actually get a log n bound. 1119 01:04:39,840 --> 01:04:41,280 For this, we need to actually know 1120 01:04:41,280 --> 01:04:43,880 a little bit about splay tree analysis. 1121 01:04:43,880 --> 01:04:46,436 I didn't cover in Lecture Six. 1122 01:04:46,436 --> 01:04:48,560 You probably would have forgotten it by now anyway. 1123 01:04:48,560 --> 01:04:50,880 So let me give you what little you need 1124 01:04:50,880 --> 01:04:54,180 to know about splay analysis. 1125 01:04:54,180 --> 01:04:57,930 First, I need to define a slightly weird quantity. 1126 01:04:57,930 --> 01:05:00,600 It's kind of like the weight of a node. 1127 01:05:00,600 --> 01:05:04,770 It's a capital W, but a little bit weird. 1128 01:05:20,600 --> 01:05:23,640 OK, now we're thinking about the tree of ox trees. 1129 01:05:23,640 --> 01:05:25,540 For the analysis we need that. 1130 01:05:25,540 --> 01:05:27,292 It's a tree of splay trees. 1131 01:05:27,292 --> 01:05:29,500 And what I'm looking at, is in that tree of ox trees, 1132 01:05:29,500 --> 01:05:31,774 how many nodes are in the subtree of v? 1133 01:05:31,774 --> 01:05:33,190 That's what I'm going to call wv . 1134 01:05:33,190 --> 01:05:36,760 Whereas size of v was thinking in the represented tree. 1135 01:05:36,760 --> 01:05:38,590 So this is a totally different world. 1136 01:05:38,590 --> 01:05:41,050 Here, we're thinking about the tree of ox trees. 1137 01:05:41,050 --> 01:05:44,640 So one way you can rewrite this count 1138 01:05:44,640 --> 01:05:54,490 as the sum of all nodes w in the ox tree containing v. It's 1139 01:05:54,490 --> 01:05:57,130 a weird notation, but look at all the other nodes in the ox 1140 01:05:57,130 --> 01:05:59,417 tree-- 1141 01:05:59,417 --> 01:06:00,000 is that right? 1142 01:06:00,000 --> 01:06:02,642 Sorry. 1143 01:06:02,642 --> 01:06:03,142 No. 1144 01:06:06,960 --> 01:06:19,140 I should say w in v's subtree in v's ox tree. 1145 01:06:19,140 --> 01:06:20,610 It's awkward to say. 1146 01:06:20,610 --> 01:06:24,930 What I mean is there is an ox tree containing a node v, 1147 01:06:24,930 --> 01:06:28,650 and I want to look in that subtree I'll know as w. 1148 01:06:28,650 --> 01:06:31,170 Just within the ox tree though. 1149 01:06:31,170 --> 01:06:35,700 And for all those nodes, I take 1 plus the size 1150 01:06:35,700 --> 01:06:38,573 of ox trees hanging off. 1151 01:06:46,970 --> 01:06:48,770 So total number of nodes. 1152 01:06:48,770 --> 01:06:52,190 And when I say hanging off I mean 1153 01:06:52,190 --> 01:06:54,930 via pathed parent pointers. 1154 01:06:54,930 --> 01:06:58,070 So down here, there are trees, add up all their sizes 1155 01:06:58,070 --> 01:07:01,820 total number of nodes in them, add one for w itself, 1156 01:07:01,820 --> 01:07:04,340 that's another way of writing this. 1157 01:07:04,340 --> 01:07:10,910 I'll just mention that this part is what's normally 1158 01:07:10,910 --> 01:07:12,530 considered in splay trees. 1159 01:07:12,530 --> 01:07:15,230 This is a bonus thing that, basically, doesn't matter. 1160 01:07:17,940 --> 01:07:20,400 I'll justify that in a second. 1161 01:07:20,400 --> 01:07:21,980 So we define a potential function 1162 01:07:21,980 --> 01:07:29,420 for our amortization fee, which is sum over all nodes v of log 1163 01:07:29,420 --> 01:07:33,500 this quantity wv, this thing. 1164 01:07:33,500 --> 01:07:37,460 So just think of this as an abstract quantity, 1165 01:07:37,460 --> 01:07:41,040 which for every node it has some number associated with it. 1166 01:07:41,040 --> 01:07:45,200 Splay trees allow you to assign arbitrary weight to every node, 1167 01:07:45,200 --> 01:07:48,350 use this potential function, and prove abound --which 1168 01:07:48,350 --> 01:07:57,700 is called the access lemma The access lemma says is that, 1169 01:07:57,700 --> 01:08:01,090 for this potential function, the amortized cost 1170 01:08:01,090 --> 01:08:12,620 of doing a splay operation splay of v, 1171 01:08:12,620 --> 01:08:30,290 is, at most, three times log w of root of v's ox tree 1172 01:08:30,290 --> 01:08:38,029 minus log w of v plus 1. 1173 01:08:41,000 --> 01:08:43,969 OK, so this is something called the access Lemma 1174 01:08:43,969 --> 01:08:46,310 It's used to prove, for example, that splay trees have 1175 01:08:46,310 --> 01:08:48,145 log n performance amortize. 1176 01:08:48,145 --> 01:08:49,520 It's also used to prove that they 1177 01:08:49,520 --> 01:08:52,040 have a working set bound, which you 1178 01:08:52,040 --> 01:08:54,229 may recall from Lecture Six. 1179 01:08:54,229 --> 01:08:57,040 But we never actually mentioned the access lemma It's a tool. 1180 01:08:57,040 --> 01:08:57,979 It's an analysis tool. 1181 01:09:00,950 --> 01:09:04,266 This works no matter how the w's are defined. 1182 01:09:04,266 --> 01:09:06,140 And remember, we're thinking of splaying just 1183 01:09:06,140 --> 01:09:07,529 within a single ox tree. 1184 01:09:07,529 --> 01:09:10,069 So the size of the ox trees hanging off 1185 01:09:10,069 --> 01:09:11,460 don't change during a splay. 1186 01:09:11,460 --> 01:09:13,500 They just come along for the ride. 1187 01:09:13,500 --> 01:09:16,712 So the old analysis of splay trees 1188 01:09:16,712 --> 01:09:18,170 I haven't proved this lemma to you. 1189 01:09:18,170 --> 01:09:21,710 But it still applies in this setting. 1190 01:09:21,710 --> 01:09:23,100 And given my lack of time. 1191 01:09:23,100 --> 01:09:25,880 I will just say in words, the way you prove 1192 01:09:25,880 --> 01:09:27,800 this lemma is very simple. 1193 01:09:27,800 --> 01:09:30,229 You do you analyze each operation of display 1194 01:09:30,229 --> 01:09:34,130 separately there's a zig-zag case in a zigzag case. 1195 01:09:34,130 --> 01:09:39,500 And you argue that every time you do such an operation, 1196 01:09:39,500 --> 01:09:44,240 you pay three times a log of w of v 1197 01:09:44,240 --> 01:09:48,740 after the operation minus log of wv before the operation. 1198 01:09:48,740 --> 01:09:51,680 So you just see how wv changes when it goes up 1199 01:09:51,680 --> 01:09:55,155 after you do display operation, and turns out it's 1200 01:09:55,155 --> 01:09:56,530 the most three times log of that. 1201 01:09:56,530 --> 01:09:58,290 And it has to do with concavity of log n. 1202 01:09:58,290 --> 01:10:00,650 It's just basic checking. 1203 01:10:00,650 --> 01:10:03,500 Once you have that you get a telescoping sum. 1204 01:10:03,500 --> 01:10:07,820 Each operation is log w new minus long w old. 1205 01:10:07,820 --> 01:10:13,070 Those cancel, in turn, until you get the final log w of v, 1206 01:10:13,070 --> 01:10:17,720 minus the original log w of v. The final log w is whatever-- 1207 01:10:17,720 --> 01:10:21,510 I mean, v becomes the root and so it has everybody below it. 1208 01:10:21,510 --> 01:10:24,440 So that's the axis lemma. 1209 01:10:24,440 --> 01:10:28,010 So assuming the access lemma, I want 1210 01:10:28,010 --> 01:10:31,480 to prove to you a log n bound. 1211 01:10:31,480 --> 01:10:53,920 Maybe over here OK, another thing to note, 1212 01:10:53,920 --> 01:10:57,430 when we change preferred children, it does not affect w. 1213 01:10:57,430 --> 01:11:01,880 W defined on the tree of ox trees. 1214 01:11:01,880 --> 01:11:03,800 If you turn a path parent pointer 1215 01:11:03,800 --> 01:11:06,975 into a regular parent pointer or vice versa, It doesn't care. 1216 01:11:06,975 --> 01:11:09,350 It looks the same from the tree of ox trees' perspective. 1217 01:11:09,350 --> 01:11:12,609 All that changes, all that matters is when you do splays 1218 01:11:12,609 --> 01:11:13,400 this stuff happens. 1219 01:11:13,400 --> 01:11:15,710 But the splay analysis tells us how splays behave. 1220 01:11:15,710 --> 01:11:18,890 So we're kind of good. 1221 01:11:18,890 --> 01:11:25,040 If you look at what we did over here, when we splayed v, 1222 01:11:25,040 --> 01:11:30,140 then we splayed w, then we did a little bit of manipulation 1223 01:11:30,140 --> 01:11:32,820 which doesn't matter in this analysis. 1224 01:11:32,820 --> 01:11:36,040 And then we splayed v one more time. 1225 01:11:36,040 --> 01:11:38,780 How much does that cost according to the access lemma. 1226 01:11:38,780 --> 01:11:43,220 It's basically going to cost you order log 1227 01:11:43,220 --> 01:11:51,620 w of little w minus log w of v plus 1, 1228 01:11:51,620 --> 01:12:00,410 because well is it clear? 1229 01:12:00,410 --> 01:12:03,830 When we do the first splay of v going up to the root 1230 01:12:03,830 --> 01:12:07,460 that cost log of w of the whole tree containing 1231 01:12:07,460 --> 01:12:10,070 b minus longer wv. 1232 01:12:10,070 --> 01:12:12,020 But if you just look at log, I mean, 1233 01:12:12,020 --> 01:12:16,580 w is higher than the root of v. So if we take a log of w 1234 01:12:16,580 --> 01:12:23,120 this the whole thing from w downwards minus log wv, that 1235 01:12:23,120 --> 01:12:27,170 includes the cost that we did for the initial splay of v. 1236 01:12:27,170 --> 01:12:30,530 Then when we played w, well that's basically the same thing 1237 01:12:30,530 --> 01:12:32,090 but the next level up. 1238 01:12:32,090 --> 01:12:38,117 So if you look at log of w minus log of w of next level up, 1239 01:12:38,117 --> 01:12:39,950 that's what it's going to cost this splay w. 1240 01:12:39,950 --> 01:12:42,950 To splay v again, will again cost this bound. 1241 01:12:42,950 --> 01:12:48,620 The point is, we sum this up over all the preferred child 1242 01:12:48,620 --> 01:12:49,670 changes. 1243 01:12:49,670 --> 01:12:53,720 And what we get is a telescoping scum again. 1244 01:12:53,720 --> 01:12:55,820 Same as in the display analysis. 1245 01:12:55,820 --> 01:13:03,290 So we end up with order log w of everything, which an n minus, 1246 01:13:03,290 --> 01:13:05,480 I guess, the log of w of the original v, 1247 01:13:05,480 --> 01:13:07,220 -but we don't really care about that-- 1248 01:13:07,220 --> 01:13:10,355 plus the number of preferred child changes. 1249 01:13:14,950 --> 01:13:18,230 And now we're golden because before, the obvious bound was 1250 01:13:18,230 --> 01:13:21,249 number preferred child changes times again, now 1251 01:13:21,249 --> 01:13:22,790 it's number of preferred time changes 1252 01:13:22,790 --> 01:13:25,790 plus log n for an entire access. 1253 01:13:25,790 --> 01:13:27,830 And so we pay log n here. 1254 01:13:27,830 --> 01:13:30,370 We already know the amortize number preferred child changes 1255 01:13:30,370 --> 01:13:32,060 is log n per operation. 1256 01:13:32,060 --> 01:13:35,930 So overall the amortize cost per operation is log n. 1257 01:13:35,930 --> 01:13:39,020 And we're done. 1258 01:13:39,020 --> 01:13:43,370 So I'll just mention the worst case version of link-cut trees 1259 01:13:43,370 --> 01:13:47,060 instead of the amortize splay based version. 1260 01:13:47,060 --> 01:13:49,710 They actually store the heavy light decomposition. 1261 01:13:49,710 --> 01:13:52,430 They don't use preferred path to decomposition at all, which 1262 01:13:52,430 --> 01:13:54,941 makes all the algorithms messy. 1263 01:13:54,941 --> 01:13:57,440 But you can just maintain the heavy [? likely ?] composition 1264 01:13:57,440 --> 01:14:00,860 position dynamically as the tree is changing, 1265 01:14:00,860 --> 01:14:04,610 and then you use a kind of weight balanced trees, 1266 01:14:04,610 --> 01:14:09,470 like we saw in the strings lecture, where 1267 01:14:09,470 --> 01:14:13,560 the depth of a node is sort of related to log of its size 1268 01:14:13,560 --> 01:14:14,910 or inversely related I guess. 1269 01:14:14,910 --> 01:14:18,410 So you try to put all the heavy things near the root, 1270 01:14:18,410 --> 01:14:20,450 because they're more likely to be accessed. 1271 01:14:20,450 --> 01:14:22,940 And then you guarantee that the overall tree of ox trees 1272 01:14:22,940 --> 01:14:27,500 has long n depth by skewing each of the end of the ox trees 1273 01:14:27,500 --> 01:14:29,822 to match. 1274 01:14:29,822 --> 01:14:32,030 So it can be done but all the operations are messier, 1275 01:14:32,030 --> 01:14:34,571 because you no longer have the convenience of preferred paths 1276 01:14:34,571 --> 01:14:37,420 to make it easy to link/cut things.