All language subtitles for singly_linked_lists-720p-en

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranî)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
fa Persian
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian Download
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu
Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated: 0 00:00:00,000 --> 00:00:02,832 >> [MUSIC PLAYING] 1 00:00:02,832 --> 00:00:05,670 2 00:00:05,670 --> 00:00:08,560 >> DOUG LLOYD: OK, so at this point in the course, 3 00:00:08,560 --> 00:00:15,300 we've covered a lot of the basics of C. We know a lot about variables, arrays, 4 00:00:15,300 --> 00:00:17,610 pointers, all that good stuff. 5 00:00:17,610 --> 00:00:21,610 Those are all sort of built in to see as the fundamentals, 6 00:00:21,610 --> 00:00:23,880 but we can do more, right? 7 00:00:23,880 --> 00:00:27,930 We can combine things together in interesting ways. 8 00:00:27,930 --> 00:00:31,010 >> And so let's do that, let's start to branch out of what C gives us, 9 00:00:31,010 --> 00:00:35,270 and start to create our own data structures using these building 10 00:00:35,270 --> 00:00:40,590 blocks together to do something really valuable, useful. 11 00:00:40,590 --> 00:00:43,420 One way we can do this is to talk about collections. 12 00:00:43,420 --> 00:00:48,360 So so far we've had one kind of data structure for representing collections 13 00:00:48,360 --> 00:00:51,030 of like values, similar values. 14 00:00:51,030 --> 00:00:52,350 That would be an array. 15 00:00:52,350 --> 00:00:57,020 We have collections of integers, or collections of characters and so on. 16 00:00:57,020 --> 00:01:00,890 >> Structures are also sort of a data structure for collecting information, 17 00:01:00,890 --> 00:01:03,220 but it's not for collecting like values. 18 00:01:03,220 --> 00:01:08,090 It usually mixes different data types together inside of a single box. 19 00:01:08,090 --> 00:01:10,750 But it's not itself used to chain together 20 00:01:10,750 --> 00:01:16,920 or connect together similar items, like an array. 21 00:01:16,920 --> 00:01:20,960 Arrays are great for element look up, but recall 22 00:01:20,960 --> 00:01:24,262 that it's very difficult to insert into an array, 23 00:01:24,262 --> 00:01:26,470 unless we're inserting at the very end of that array. 24 00:01:26,470 --> 00:01:29,730 >> And the best example I have for that is insertion sort. 25 00:01:29,730 --> 00:01:31,650 If you recall our video on insertion sort, 26 00:01:31,650 --> 00:01:34,110 there was a lot of expense involved in having 27 00:01:34,110 --> 00:01:37,970 to pick up elements, and shift them out of the way to fit something 28 00:01:37,970 --> 00:01:41,290 into the middle of your array. 29 00:01:41,290 --> 00:01:44,690 Arrays also suffer from another problem, which is inflexibility. 30 00:01:44,690 --> 00:01:47,150 When we declare an array, we get one shot at it. 31 00:01:47,150 --> 00:01:49,790 We get to say, I want this many elements. 32 00:01:49,790 --> 00:01:51,940 Might be 100, it might be 1,000, it might 33 00:01:51,940 --> 00:01:55,930 be x where x is a number that the user gave us at a prompt or at the command 34 00:01:55,930 --> 00:01:56,630 line. 35 00:01:56,630 --> 00:01:59,905 >> But we only get one shot at it, we don't get to then say oh, actually I 36 00:01:59,905 --> 00:02:04,360 needed 101, or I needed x plus 20. 37 00:02:04,360 --> 00:02:07,910 Too late, we've already declared the array, and if we want to get 101 or x 38 00:02:07,910 --> 00:02:12,050 plus 20, we have to declare an entirely different array, 39 00:02:12,050 --> 00:02:15,540 copy all the elements of the array over, and then we have enough. 40 00:02:15,540 --> 00:02:19,880 And what if we are wrong again, what if we actually need 102, or x plus 40, 41 00:02:19,880 --> 00:02:21,970 we have to do this again. 42 00:02:21,970 --> 00:02:26,250 So they're very inflexible for resizing our data, 43 00:02:26,250 --> 00:02:29,360 but if we combine together some of the basics that we've already 44 00:02:29,360 --> 00:02:33,230 learned about pointers and structures, in particular using dynamic memory 45 00:02:33,230 --> 00:02:36,180 allocation with malloc, we can put these pieces together 46 00:02:36,180 --> 00:02:40,960 to create a new data structure-- a singly linked list we might say-- 47 00:02:40,960 --> 00:02:45,400 that allows us to grow and shrink a collection of values 48 00:02:45,400 --> 00:02:48,800 and we won't have any wasted space. 49 00:02:48,800 --> 00:02:53,320 >> So again, we call this idea, this notion, a linked list. 50 00:02:53,320 --> 00:02:56,320 In particular, in this video we're talking about singly linked list, 51 00:02:56,320 --> 00:02:59,185 and then another video we'll talk about doubly linked lists, which 52 00:02:59,185 --> 00:03:01,560 is just a variation on a theme here. 53 00:03:01,560 --> 00:03:05,200 But a singly linked list is comprised of nodes, 54 00:03:05,200 --> 00:03:08,559 nodes just being an abstract term-- it's just something I'm calling 55 00:03:08,559 --> 00:03:10,350 that's a kind of structure, basically, I'm? 56 00:03:10,350 --> 00:03:16,190 Just going to call it a node-- and this node has two members, or two fields. 57 00:03:16,190 --> 00:03:20,300 It has data, usually an integer, a character float, 58 00:03:20,300 --> 00:03:23,790 or could be some other data type that you've defined with a type def. 59 00:03:23,790 --> 00:03:29,290 And it contains a pointer to another node of the same type. 60 00:03:29,290 --> 00:03:34,710 >> So we have two things inside of this node, data and a pointer 61 00:03:34,710 --> 00:03:36,380 to another node. 62 00:03:36,380 --> 00:03:39,370 And if you start to visualize this, you can think about it 63 00:03:39,370 --> 00:03:42,280 like a chain of nodes that are connected together. 64 00:03:42,280 --> 00:03:45,070 We have the first node, it contains data, and a pointer 65 00:03:45,070 --> 00:03:49,110 to the second node, which contains data, and a pointer to the third node. 66 00:03:49,110 --> 00:03:52,940 And so that's why we call it a linked list, they're linked together. 67 00:03:52,940 --> 00:03:56,070 >> What does this special node structure look like? 68 00:03:56,070 --> 00:04:01,120 Well, if you recall from our video on defining custom types, with type def, 69 00:04:01,120 --> 00:04:05,400 we can define a structure-- and type define a structure like this. 70 00:04:05,400 --> 00:04:11,240 tyepdef struct sllist, and then I'm using the word value here arbitrarily 71 00:04:11,240 --> 00:04:13,891 to indicate any data type really. 72 00:04:13,891 --> 00:04:16,890 You could pass on an integer or float, you could have whatever you want. 73 00:04:16,890 --> 00:04:19,389 It's not restricted to just integers, or anything like that. 74 00:04:19,389 --> 00:04:22,790 So value is just an arbitrary data type, and then a pointer 75 00:04:22,790 --> 00:04:26,310 to another node of the same type. 76 00:04:26,310 --> 00:04:29,690 >> Now, there's a little catch here with defining a structure 77 00:04:29,690 --> 00:04:33,030 when it's a self referential structure. 78 00:04:33,030 --> 00:04:35,340 I have to have a temporary name for my structure. 79 00:04:35,340 --> 00:04:37,640 At the end of the day I clearly want to call it 80 00:04:37,640 --> 00:04:43,030 sll node, that's ultimately the new name part of my type definition, 81 00:04:43,030 --> 00:04:47,450 but I can't use sll node in the middle of this. 82 00:04:47,450 --> 00:04:51,430 The reason being, I haven't created a type called sll node 83 00:04:51,430 --> 00:04:55,200 until I hit this final point here. 84 00:04:55,200 --> 00:04:59,720 Up until that point, I have to have another way to refer to this data type. 85 00:04:59,720 --> 00:05:02,440 >> And this is a self referential data type. 86 00:05:02,440 --> 00:05:06,314 It;s a data type of a structure that contains a data, 87 00:05:06,314 --> 00:05:08,480 and a pointer to another structure of the same type. 88 00:05:08,480 --> 00:05:11,750 So I need to be able to refer to this data type at least temporarily, 89 00:05:11,750 --> 00:05:14,910 so giving it a temporary name of struct sllist 90 00:05:14,910 --> 00:05:18,540 allows me to then say I want a pointer to another struct sllist, 91 00:05:18,540 --> 00:05:24,690 a struct sllist star, and then after I've completed the definition, 92 00:05:24,690 --> 00:05:27,220 I can now call this type an sll node. 93 00:05:27,220 --> 00:05:30,520 >> So that's why you see there's a temporary name here, 94 00:05:30,520 --> 00:05:31,879 but a permanent name here. 95 00:05:31,879 --> 00:05:33,920 Sometimes you might see definitions of structure, 96 00:05:33,920 --> 00:05:36,570 for example, that aren't self referential, that 97 00:05:36,570 --> 00:05:39,390 don't have a specifier name here. 98 00:05:39,390 --> 00:05:43,040 It would just say typedef struct, open curly brace and then define it. 99 00:05:43,040 --> 00:05:45,620 But if you're struct is self referential, as this one is, 100 00:05:45,620 --> 00:05:49,010 you need to specify a temporary type name. 101 00:05:49,010 --> 00:05:51,310 But ultimately, now that we've done this, 102 00:05:51,310 --> 00:05:53,620 we can just refer to these nodes, these units, 103 00:05:53,620 --> 00:05:57,900 as sll nodes for purposes of the rest of this video. 104 00:05:57,900 --> 00:06:00,900 >> All right, so we know how to create a linked list node. 105 00:06:00,900 --> 00:06:03,240 We know how to define a linked list node. 106 00:06:03,240 --> 00:06:06,670 Now, if we're going to start using them to collect information, 107 00:06:06,670 --> 00:06:10,360 there's a couple of operations we need to understand and work with. 108 00:06:10,360 --> 00:06:12,860 We need to know how to create a linked list out of thin air. 109 00:06:12,860 --> 00:06:14,901 If there's no list already, we want to start one. 110 00:06:14,901 --> 00:06:16,960 So we need to be able to create a linked list, 111 00:06:16,960 --> 00:06:19,130 we need to probably search through the link list 112 00:06:19,130 --> 00:06:21,830 to find an element we're looking for. 113 00:06:21,830 --> 00:06:24,430 We need to be able to insert new things into the list, 114 00:06:24,430 --> 00:06:25,930 we want our list to be able to grow. 115 00:06:25,930 --> 00:06:28,638 And similarly, we want to be able to delete things from our list, 116 00:06:28,638 --> 00:06:30,250 we want our list to be able to shrink. 117 00:06:30,250 --> 00:06:32,160 And at the end of our programs, especially 118 00:06:32,160 --> 00:06:34,550 if you recall that we're dynamically allocating memory 119 00:06:34,550 --> 00:06:38,337 to build these lists typically, we want to free all of that memory 120 00:06:38,337 --> 00:06:39,670 when we're done working with it. 121 00:06:39,670 --> 00:06:44,627 And so we need to be able to delete an entire linked list in one fail swoop. 122 00:06:44,627 --> 00:06:46,460 So let's go through some of these operations 123 00:06:46,460 --> 00:06:51,192 and how we might visualize them, talking in pseudocode code specifically. 124 00:06:51,192 --> 00:06:53,150 So we want to create a linked list, so maybe we 125 00:06:53,150 --> 00:06:56,480 want to define a function with this prototype. 126 00:06:56,480 --> 00:07:01,690 sll node star, create, and I'm passing in one argument, some arbitrary data 127 00:07:01,690 --> 00:07:05,530 type again, of some arbitrary data type. 128 00:07:05,530 --> 00:07:10,482 But I'm returning-- this function should return to me a pointer, to a singly 129 00:07:10,482 --> 00:07:11,190 linked list node. 130 00:07:11,190 --> 00:07:14,050 Again, we're trying to create a linked list out of thin air, 131 00:07:14,050 --> 00:07:17,900 so I need a pointer to that list when I'm done. 132 00:07:17,900 --> 00:07:19,420 >> So what are the steps involved here? 133 00:07:19,420 --> 00:07:20,960 Well, first thing I'm going to do is dynamically 134 00:07:20,960 --> 00:07:22,550 allocate space for a new node. 135 00:07:22,550 --> 00:07:26,689 Again, we're creating it out of thin air, so we need to malloc space for it. 136 00:07:26,689 --> 00:07:28,480 And of course, immediately after we malloc, 137 00:07:28,480 --> 00:07:31,692 we always check to make sure that our pointer-- we did not get back null. 138 00:07:31,692 --> 00:07:33,650 Because if we try and deference a null pointer, 139 00:07:33,650 --> 00:07:36,190 we're going to suffer a segfault and we don't want that. 140 00:07:36,190 --> 00:07:39,510 >> Then we want to fill in the field, we want to initialize the value field 141 00:07:39,510 --> 00:07:41,690 and initialize the next field. 142 00:07:41,690 --> 00:07:45,450 And then we want to-- eventually as the function prototype indicates-- we want 143 00:07:45,450 --> 00:07:49,940 to return a pointer to an sll node. 144 00:07:49,940 --> 00:07:51,710 So what make this look like visually? 145 00:07:51,710 --> 00:07:55,230 Well, first we're going to dynamically allocate space for a new sll node, 146 00:07:55,230 --> 00:07:58,320 so we malloc-- that's a visual representation 147 00:07:58,320 --> 00:08:00,020 of the node we just created. 148 00:08:00,020 --> 00:08:02,757 And we check to make sure it's not null-- in this case, 149 00:08:02,757 --> 00:08:04,840 the picture wouldn't have shown up if it was null, 150 00:08:04,840 --> 00:08:07,298 we would have run out of memory, so we're good to go there. 151 00:08:07,298 --> 00:08:10,200 So now we're on to step C, initialize the nodes value field. 152 00:08:10,200 --> 00:08:12,280 Well, based on this function call I'm using here, 153 00:08:12,280 --> 00:08:16,700 looks like I want to pass in 6, so I'll 6 in the value field. 154 00:08:16,700 --> 00:08:18,865 Now, initialize the next field. 155 00:08:18,865 --> 00:08:21,640 Well, what am I going to do there, there is nothing next, right, 156 00:08:21,640 --> 00:08:23,600 this is the only thing in the list. 157 00:08:23,600 --> 00:08:27,206 So what's the next thing in the list? 158 00:08:27,206 --> 00:08:29,660 >> It shouldn't point to anything, right. 159 00:08:29,660 --> 00:08:33,600 There's nothing else there, so what is the concept we know of that's nothing-- 160 00:08:33,600 --> 00:08:35,638 pointers to nothing? 161 00:08:35,638 --> 00:08:37,929 It should be maybe we want to put a null pointer there, 162 00:08:37,929 --> 00:08:40,178 and I'll represent the null pointer as just a red box, 163 00:08:40,178 --> 00:08:41,559 we can't go any further. 164 00:08:41,559 --> 00:08:44,430 As we'll see a little later on, we will have eventually chains 165 00:08:44,430 --> 00:08:46,330 of arrows connecting these nodes together, 166 00:08:46,330 --> 00:08:48,480 but when you hit the red box, that's null, 167 00:08:48,480 --> 00:08:51,150 we can't go any further, that's the end of the list. 168 00:08:51,150 --> 00:08:53,960 >> And lastly, we just want to return a pointer to this node. 169 00:08:53,960 --> 00:08:56,160 So we'll call it new, and will return new 170 00:08:56,160 --> 00:08:59,370 so it can be used in whatever function created it. 171 00:08:59,370 --> 00:09:03,100 So there we go, We've created a singly linked list node out of thin air, 172 00:09:03,100 --> 00:09:05,920 and now we have a list we can work with. 173 00:09:05,920 --> 00:09:08,260 >> Now, let's say we already have a large chain, 174 00:09:08,260 --> 00:09:09,800 and we want to find something in it. 175 00:09:09,800 --> 00:09:12,716 And we want a function that's going to return true or false, depending 176 00:09:12,716 --> 00:09:15,840 on whether a value exists in that list. 177 00:09:15,840 --> 00:09:18,160 A function prototype, or declaration for that function, 178 00:09:18,160 --> 00:09:23,320 might look like this-- bool find, and then we want to pass in two arguments. 179 00:09:23,320 --> 00:09:26,996 >> The first, is a pointer to the first element of the linked list. 180 00:09:26,996 --> 00:09:29,620 This is actually something you'll always want to keep track of, 181 00:09:29,620 --> 00:09:33,110 and actually might be something that you even put in a global variable. 182 00:09:33,110 --> 00:09:35,360 Once you create a list, you always, always 183 00:09:35,360 --> 00:09:38,990 want to keep track of the very first element of the list. 184 00:09:38,990 --> 00:09:43,690 That way you can refer to all the other elements by just following the chain, 185 00:09:43,690 --> 00:09:47,300 without having to keep pointers intact to every single element. 186 00:09:47,300 --> 00:09:50,920 You only need to keep track of the first one if they're all chained together. 187 00:09:50,920 --> 00:09:52,460 >> And then the second thing we're passing in again 188 00:09:52,460 --> 00:09:54,376 is arbitrarily some-- whatever data type we're 189 00:09:54,376 --> 00:09:59,640 looking for there is inside of hopefully one of the nodes in the list. 190 00:09:59,640 --> 00:10:00,980 So what are the steps? 191 00:10:00,980 --> 00:10:04,250 Well, the first thing we do is we create a transversal pointer 192 00:10:04,250 --> 00:10:06,015 pointing to the lists head. 193 00:10:06,015 --> 00:10:08,890 Well, why do we do that, we already have a pointer at the lists head, 194 00:10:08,890 --> 00:10:10,974 why don't we just move that one around? 195 00:10:10,974 --> 00:10:13,140 Well, like I just said, it's really important for us 196 00:10:13,140 --> 00:10:17,580 to always keep track of the very first element in the list. 197 00:10:17,580 --> 00:10:21,270 And so it's actually better to create a duplicate of that, 198 00:10:21,270 --> 00:10:25,350 and use that to move around so we never accidentally move away, or we always 199 00:10:25,350 --> 00:10:30,430 have a pointer at some point that is right on the first element of the list. 200 00:10:30,430 --> 00:10:33,290 So it's better to create a second one that we use to move. 201 00:10:33,290 --> 00:10:35,877 >> Then we just compare whether the value field at that node 202 00:10:35,877 --> 00:10:38,960 is what we're looking for, and if it's not, we just move to the next node. 203 00:10:38,960 --> 00:10:41,040 And we keep doing that over, and over, and over, 204 00:10:41,040 --> 00:10:44,811 until we either find the element, or we hit 205 00:10:44,811 --> 00:10:47,310 null-- we've reached the end of the list and it isn't there. 206 00:10:47,310 --> 00:10:50,540 This should hopefully ring a bell to you as just linear search, 207 00:10:50,540 --> 00:10:54,430 we're just replicating it in a singly linked list structure 208 00:10:54,430 --> 00:10:56,280 instead of using an array to do it. 209 00:10:56,280 --> 00:10:58,210 >> So here's an example of a singly linked list. 210 00:10:58,210 --> 00:11:00,043 This one consists of five nodes, and we have 211 00:11:00,043 --> 00:11:04,330 a pointer to the head of the list, which is called list. 212 00:11:04,330 --> 00:11:07,385 The first thing we want to do is again, create that traversal pointer. 213 00:11:07,385 --> 00:11:09,760 So we have now two pointers that point to the same thing. 214 00:11:09,760 --> 00:11:15,025 >> Now, notice here also, I didn't have to malloc any space for trav. 215 00:11:15,025 --> 00:11:18,970 I didn't say trav equals malloc something, that node already exists, 216 00:11:18,970 --> 00:11:21,160 that space in memory already exists. 217 00:11:21,160 --> 00:11:24,290 So all I'm actually doing is creating another pointer to it. 218 00:11:24,290 --> 00:11:28,210 I'm not mallocing an additional space, just have now two pointers 219 00:11:28,210 --> 00:11:31,370 pointing to the same thing. 220 00:11:31,370 --> 00:11:33,710 >> So is 2 what I'm looking for? 221 00:11:33,710 --> 00:11:37,220 Well, no, so instead I'm going to move to the next one. 222 00:11:37,220 --> 00:11:41,740 So basically I would say, trav equals trav next. 223 00:11:41,740 --> 00:11:43,630 Is 3 what I'm looking for, no. 224 00:11:43,630 --> 00:11:45,780 So I continue to go through, until eventually 225 00:11:45,780 --> 00:11:48,690 get to 6 which is what I'm looking for based on the function call 226 00:11:48,690 --> 00:11:51,600 I have at the top there, and so I'm done. 227 00:11:51,600 --> 00:11:54,150 >> Now, what if the element I'm looking for isn't in the list, 228 00:11:54,150 --> 00:11:55,510 is it still going to work? 229 00:11:55,510 --> 00:11:57,120 Well, notice that the list here is subtly different, 230 00:11:57,120 --> 00:11:59,410 and this is another thing that's important with linked lists, 231 00:11:59,410 --> 00:12:01,780 you don't have to preserve them in any particular order. 232 00:12:01,780 --> 00:12:05,390 You can if you want, but you may have already noticed 233 00:12:05,390 --> 00:12:09,310 that we're not keeping track of what number element we are at. 234 00:12:09,310 --> 00:12:13,150 >> And that's sort of one trade that we have with linked list verses arrays, 235 00:12:13,150 --> 00:12:15,300 is it we don't have random access anymore. 236 00:12:15,300 --> 00:12:18,150 We can't just say, I want to go to the 0th element, 237 00:12:18,150 --> 00:12:21,410 or the 6th element of my array, which I can do in an array. 238 00:12:21,410 --> 00:12:25,080 I can't say I want to go to the 0th element, or the 6th element, 239 00:12:25,080 --> 00:12:30,360 or the 25th element of my linked list, there's no index associated with them. 240 00:12:30,360 --> 00:12:33,660 And so it doesn't really matter if we preserve our list in order. 241 00:12:33,660 --> 00:12:36,080 If you want to you certainly can, but there's 242 00:12:36,080 --> 00:12:38,567 no reason why they need to be preserved in any order. 243 00:12:38,567 --> 00:12:40,400 So again, let's try and find 6 in this list. 244 00:12:40,400 --> 00:12:43,200 Well, we start at the beginning, we don't find 6, 245 00:12:43,200 --> 00:12:47,690 and then we continue not finding 6, until we eventually get to here. 246 00:12:47,690 --> 00:12:52,790 So right now trav points to the node containing 8, and six is not in there. 247 00:12:52,790 --> 00:12:55,250 >> So the next step would be to go to the next pointer, 248 00:12:55,250 --> 00:12:57,440 so say trav equals trav next. 249 00:12:57,440 --> 00:13:00,750 Well, trav next, indicated by the red box there, is null. 250 00:13:00,750 --> 00:13:03,020 So there's nowhere else to go, and so at this point 251 00:13:03,020 --> 00:13:06,120 we can conclude that we've reached the end of the linked list, 252 00:13:06,120 --> 00:13:07,190 and 6 isn't in there. 253 00:13:07,190 --> 00:13:10,980 And it would be returned false in this case. 254 00:13:10,980 --> 00:13:14,540 >> OK, how do we insert a new node into the linked list? 255 00:13:14,540 --> 00:13:17,310 So we've been able to create a linked list out of nowhere, 256 00:13:17,310 --> 00:13:19,370 but we probably want to build a chain and not 257 00:13:19,370 --> 00:13:22,620 create a bunch of distinct lists. 258 00:13:22,620 --> 00:13:25,700 We want to have one list that has a bunch of nodes in it, 259 00:13:25,700 --> 00:13:28,040 not a bunch of lists with a single node. 260 00:13:28,040 --> 00:13:31,260 So we can't just keep using the Create function we defined earlier, now we 261 00:13:31,260 --> 00:13:33,860 want to insert into a list that already exists. 262 00:13:33,860 --> 00:13:36,499 >> So this case, we're going to pass in two arguments, 263 00:13:36,499 --> 00:13:39,290 the pointer to the head of that linked list that we want to add to. 264 00:13:39,290 --> 00:13:40,910 Again, that's why it's so important that we always 265 00:13:40,910 --> 00:13:43,400 keep track of it, because it's the only way we really 266 00:13:43,400 --> 00:13:46,690 have to refer to the whole list is just by a pointer to the first element. 267 00:13:46,690 --> 00:13:49,360 So we want to pass in a pointer to that first element, 268 00:13:49,360 --> 00:13:52,226 and whatever value we want to add to the list. 269 00:13:52,226 --> 00:13:54,600 And eventually this function is going to return a pointer 270 00:13:54,600 --> 00:13:57,980 to the new head of a linked list. 271 00:13:57,980 --> 00:13:59,700 >> What are the steps involved here? 272 00:13:59,700 --> 00:14:02,249 Well, just like with create, we need to dynamically allocate 273 00:14:02,249 --> 00:14:05,540 space for a new node, and check to make sure we don't run out of memory, again, 274 00:14:05,540 --> 00:14:07,150 because we're using malloc. 275 00:14:07,150 --> 00:14:09,080 Then we want to populate and insert the node, 276 00:14:09,080 --> 00:14:12,730 so put the number, whatever val is, into the node. 277 00:14:12,730 --> 00:14:17,310 We want to insert the node at the beginning of the linked list. 278 00:14:17,310 --> 00:14:19,619 >> There's a reason that I want to do this, and it 279 00:14:19,619 --> 00:14:21,910 might be worth taking a second to pause the video here, 280 00:14:21,910 --> 00:14:25,860 and think about why I would want to insert at the beginning of a linked 281 00:14:25,860 --> 00:14:26,589 list. 282 00:14:26,589 --> 00:14:28,630 Again, I mentioned earlier that it doesn't really 283 00:14:28,630 --> 00:14:33,020 matter if we preserve it in any order, so maybe that's a clue. 284 00:14:33,020 --> 00:14:36,040 And you saw what would happen if we wanted to-- or from just a second 285 00:14:36,040 --> 00:14:37,360 ago when we were going through search you 286 00:14:37,360 --> 00:14:39,235 could see what might happen if we were trying 287 00:14:39,235 --> 00:14:41,330 to insert at the end of the list. 288 00:14:41,330 --> 00:14:44,750 Because we don't have a pointer to the end of the list. 289 00:14:44,750 --> 00:14:47,490 >> So the reason that I would want to insert at the beginning, 290 00:14:47,490 --> 00:14:49,380 is because I can do it immediately. 291 00:14:49,380 --> 00:14:52,730 I have a pointer at the beginning, and we'll see this in a visual in a second. 292 00:14:52,730 --> 00:14:55,605 But if I want to insert at the end, I have to start at the beginning, 293 00:14:55,605 --> 00:14:58,760 traverse all the way to the end, and then tack it on. 294 00:14:58,760 --> 00:15:01,420 So that would mean that inserting at the end of the list 295 00:15:01,420 --> 00:15:04,140 would become an o of n operation, going back 296 00:15:04,140 --> 00:15:06,720 to our discussion of computational complexity. 297 00:15:06,720 --> 00:15:10,140 It'd become an o of n operation, where as the list got bigger, and bigger, 298 00:15:10,140 --> 00:15:13,310 and bigger, it'll become more and more difficult to tack something 299 00:15:13,310 --> 00:15:14,661 on at the end. 300 00:15:14,661 --> 00:15:17,410 But it's always really easy to tack something on at the beginning, 301 00:15:17,410 --> 00:15:19,060 you're always at the beginning. 302 00:15:19,060 --> 00:15:21,620 >> And we'll see a visual of this again. 303 00:15:21,620 --> 00:15:24,100 And then once we're done, once we've inserted the new node, 304 00:15:24,100 --> 00:15:26,880 we want to return our pointer to the new head of a linked list, which 305 00:15:26,880 --> 00:15:29,213 since we're inserting at the beginning, will actually be 306 00:15:29,213 --> 00:15:31,060 a pointer to the node we just created. 307 00:15:31,060 --> 00:15:33,280 Let's visualize this, because I think it'll help. 308 00:15:33,280 --> 00:15:36,661 >> So here's our list, it consists of four elements, a node containing 15, 309 00:15:36,661 --> 00:15:38,410 which points to a node containing 9, which 310 00:15:38,410 --> 00:15:41,370 points to a node containing 13, which points to a node containing 311 00:15:41,370 --> 00:15:44,840 10, which has the null pointer as its next pointer 312 00:15:44,840 --> 00:15:47,010 so that's the end of the list. 313 00:15:47,010 --> 00:15:50,200 So we want to insert a new node with the value 12 314 00:15:50,200 --> 00:15:52,720 at the beginning of this list, what do we do? 315 00:15:52,720 --> 00:15:58,770 Well, first we malloc space for the node, and then we put 12 in there. 316 00:15:58,770 --> 00:16:02,211 >> So now we've reached a decision point, right? 317 00:16:02,211 --> 00:16:03,960 We have a couple of pointers that we could 318 00:16:03,960 --> 00:16:06,770 move, which one should we move first? 319 00:16:06,770 --> 00:16:09,250 Should we make 12 point to the new head of the list-- 320 00:16:09,250 --> 00:16:13,020 or excuse me, should we make 12 point to the old head of the list? 321 00:16:13,020 --> 00:16:15,319 Or should we say that the list now begins at 12. 322 00:16:15,319 --> 00:16:17,110 There's a distinction there, and we'll look 323 00:16:17,110 --> 00:16:19,870 at what happens with both in a second. 324 00:16:19,870 --> 00:16:23,350 >> But this leads to a great topic for sidebar, 325 00:16:23,350 --> 00:16:26,280 which is that one of the trickiest things with linked lists 326 00:16:26,280 --> 00:16:30,980 is to arrange the pointers in the correct order. 327 00:16:30,980 --> 00:16:34,520 If you move things out of order, you can end up accidentally 328 00:16:34,520 --> 00:16:36,050 orphaning the rest of the list. 329 00:16:36,050 --> 00:16:37,300 And here's an example of that. 330 00:16:37,300 --> 00:16:40,540 So let's go with the idea of-- well, we've just created 12. 331 00:16:40,540 --> 00:16:43,180 We know 12 is going to be the new head of the list, 332 00:16:43,180 --> 00:16:47,660 and so why don't we just move the list pointer to point there. 333 00:16:47,660 --> 00:16:49,070 >> OK, so that's good. 334 00:16:49,070 --> 00:16:51,560 So now where does 12 next point? 335 00:16:51,560 --> 00:16:54,580 I mean, visually we can see that it will point to 15, 336 00:16:54,580 --> 00:16:57,250 as humans it's really obvious to us. 337 00:16:57,250 --> 00:17:00,300 How does the computer know? 338 00:17:00,300 --> 00:17:02,720 We don't have anything pointing to 15 anymore, right? 339 00:17:02,720 --> 00:17:05,869 >> We've lost any ability to refer to 15. 340 00:17:05,869 --> 00:17:11,460 We can't say new arrow next equals something, there's nothing there. 341 00:17:11,460 --> 00:17:13,510 In fact, we've orphaned the rest of the list 342 00:17:13,510 --> 00:17:16,465 by doing so, we've accidentally broken the chain. 343 00:17:16,465 --> 00:17:18,089 And we certainly don't want to do that. 344 00:17:18,089 --> 00:17:20,000 >> So let's go back and try this again. 345 00:17:20,000 --> 00:17:24,060 Maybe the right thing to do is to set 12's next pointer 346 00:17:24,060 --> 00:17:28,290 to the old head of the list first, then we can move the list over. 347 00:17:28,290 --> 00:17:30,420 And in fact, that is the correct order that we 348 00:17:30,420 --> 00:17:32,836 need to follow when we're working with singly linked list. 349 00:17:32,836 --> 00:17:36,460 We always want to connect the new element into the list, 350 00:17:36,460 --> 00:17:41,010 before we take that kind of important step of changing 351 00:17:41,010 --> 00:17:43,360 where the head of the linked list is. 352 00:17:43,360 --> 00:17:46,740 Again, that's such a fundamental thing, we don't want to lose track of it. 353 00:17:46,740 --> 00:17:49,310 >> So we want to make sure that everything is chained together, 354 00:17:49,310 --> 00:17:52,040 before we move that pointer. 355 00:17:52,040 --> 00:17:55,300 And so this would be the correct order, which is to connect 12 to the list, 356 00:17:55,300 --> 00:17:57,630 then say that the list starts a 12. 357 00:17:57,630 --> 00:18:00,860 If we said the list starts at 12 and then tried to connect 12 to the list, 358 00:18:00,860 --> 00:18:02,193 we've already seen what happens. 359 00:18:02,193 --> 00:18:04,920 We lose the list by mistake. 360 00:18:04,920 --> 00:18:06,740 >> OK, so one more thing to talk about. 361 00:18:06,740 --> 00:18:09,750 What if we want to get rid of an entire linked list at once? 362 00:18:09,750 --> 00:18:11,750 Again, we're mallocing all this space, and so we 363 00:18:11,750 --> 00:18:13,351 need to free it when we're done. 364 00:18:13,351 --> 00:18:15,350 So now we want to delete the entire linked list. 365 00:18:15,350 --> 00:18:16,850 Well, what do we want to do? 366 00:18:16,850 --> 00:18:20,460 >> If we've reached the null pointer, we want to stop, otherwise, just delete 367 00:18:20,460 --> 00:18:23,420 the rest of the list and then free me. 368 00:18:23,420 --> 00:18:28,890 Delete the rest of the list, and then free the current node. 369 00:18:28,890 --> 00:18:32,850 What does that sound like, what technique have we talked 370 00:18:32,850 --> 00:18:35,440 about previously does that sound like? 371 00:18:35,440 --> 00:18:39,560 Delete everybody else, then come back and delete me. 372 00:18:39,560 --> 00:18:42,380 >> That's recursion, we've made the problem a little bit smaller, 373 00:18:42,380 --> 00:18:46,910 we're saying delete everybody else, then you can delete me. 374 00:18:46,910 --> 00:18:50,940 And further down the road, that node will say, delete everybody else. 375 00:18:50,940 --> 00:18:53,940 But eventually we'll get to the point where the list is null, 376 00:18:53,940 --> 00:18:55,310 and that's our base case. 377 00:18:55,310 --> 00:18:57,010 >> So let's take a look at this, and how this might work. 378 00:18:57,010 --> 00:18:59,759 So here's our list, it's the same list we were just talking about, 379 00:18:59,759 --> 00:19:00,980 and there's the steps. 380 00:19:00,980 --> 00:19:04,200 There's a lot of text here, but hopefully the visualization will help. 381 00:19:04,200 --> 00:19:08,557 >> So we have-- and I also pulled up our stack frames illustration 382 00:19:08,557 --> 00:19:10,890 from our video on call stacks, and hopefully all of this 383 00:19:10,890 --> 00:19:13,260 together will show you what's going on. 384 00:19:13,260 --> 00:19:14,510 So here's our pseudocode code. 385 00:19:14,510 --> 00:19:17,830 If we reach a null pointer, stop, otherwise, 386 00:19:17,830 --> 00:19:21,320 delete the rest of the list, then free the current node. 387 00:19:21,320 --> 00:19:25,700 So right now, list-- the pointer that we're 388 00:19:25,700 --> 00:19:28,410 passing in to destroy points to 12. 389 00:19:28,410 --> 00:19:33,340 12 is not a null pointer, so we're going to delete the rest of the list. 390 00:19:33,340 --> 00:19:35,450 >> What is deleting the rest of us involved? 391 00:19:35,450 --> 00:19:37,950 Well, it means making a call to destroy, saying 392 00:19:37,950 --> 00:19:42,060 that 15 is the beginning of the rest of the list we want to destroy. 393 00:19:42,060 --> 00:19:47,480 And so the call to destroy 12 is kind of on hold. 394 00:19:47,480 --> 00:19:52,690 It's frozen there, waiting for the call to destroy 15, to finish its job. 395 00:19:52,690 --> 00:19:56,280 >> Well, 15 is not a null pointer, and so it's going to say, all right, 396 00:19:56,280 --> 00:19:58,450 well, delete the rest of the list. 397 00:19:58,450 --> 00:20:00,760 The rest of the list starts at 9, and so we'll just 398 00:20:00,760 --> 00:20:04,514 wait until you delete all that stuff, then come back and delete me. 399 00:20:04,514 --> 00:20:06,680 Well 9's going to say, well, I'm not a null pointer, 400 00:20:06,680 --> 00:20:09,020 so delete the rest the list from here. 401 00:20:09,020 --> 00:20:11,805 And so try and destroy 13. 402 00:20:11,805 --> 00:20:15,550 13 says, I'm not null pointer, same thing, it passes the buck. 403 00:20:15,550 --> 00:20:17,930 10 is not null pointer, 10 contains a null pointer, 404 00:20:17,930 --> 00:20:20,200 but 10 is not itself a null pointer right now, 405 00:20:20,200 --> 00:20:22,470 and so it passes the buck too. 406 00:20:22,470 --> 00:20:25,560 >> And now list points there, it really would point to some-- 407 00:20:25,560 --> 00:20:28,710 if I had more space in the image, it would point to some random space 408 00:20:28,710 --> 00:20:29,960 that we don't know what it is. 409 00:20:29,960 --> 00:20:34,680 It's the null pointer though, the list is literally now set it's values null. 410 00:20:34,680 --> 00:20:36,820 It's pointing right inside that red box. 411 00:20:36,820 --> 00:20:39,960 We reached a null pointer, so we can stop, and we're done. 412 00:20:39,960 --> 00:20:46,230 >> And so that purple frame is now-- at the top of stack-- that's the active frame, 413 00:20:46,230 --> 00:20:47,017 but it's done. 414 00:20:47,017 --> 00:20:48,600 If we've reached a null pointer, stop. 415 00:20:48,600 --> 00:20:51,290 We don't do anything, we can't free a null pointer, 416 00:20:51,290 --> 00:20:55,070 we didn't malloc any space, and so we're done. 417 00:20:55,070 --> 00:20:57,590 So that function frame is destroyed, and we 418 00:20:57,590 --> 00:21:00,930 resume-- we pick up where we left off with the next highest one, which 419 00:21:00,930 --> 00:21:02,807 is this dark blue frame here. 420 00:21:02,807 --> 00:21:04,390 So we pick up right where we left off. 421 00:21:04,390 --> 00:21:06,598 We deleted the rest of the list already, so now we're 422 00:21:06,598 --> 00:21:08,000 going to free the current nodes. 423 00:21:08,000 --> 00:21:12,920 So now we can free this node, and now we've reached the end of the function. 424 00:21:12,920 --> 00:21:16,810 And so that function frame is destroyed, and we pick up at the light blue one. 425 00:21:16,810 --> 00:21:20,650 >> So it says-- I've already done-- deleting the rest of the list, so 426 00:21:20,650 --> 00:21:23,140 free the current node. 427 00:21:23,140 --> 00:21:26,520 And now the yellow frame is back on top of the stack. 428 00:21:26,520 --> 00:21:29,655 And so as you see, we're now destroying the list from right to left. 429 00:21:29,655 --> 00:21:33,710 430 00:21:33,710 --> 00:21:37,280 >> What would have happened, though, if we had done things the wrong way? 431 00:21:37,280 --> 00:21:39,410 Just like when we tried to add an element. 432 00:21:39,410 --> 00:21:41,909 If we messed up the chain, if we didn't connect the pointers 433 00:21:41,909 --> 00:21:44,690 in the correct order, if we just freed the first element, 434 00:21:44,690 --> 00:21:47,420 if we just freed the head of the list, now we 435 00:21:47,420 --> 00:21:49,642 have no way to refer to the rest of the list. 436 00:21:49,642 --> 00:21:51,350 And so we would have orphaned everything, 437 00:21:51,350 --> 00:21:53,880 we would have had what's called a memory leak. 438 00:21:53,880 --> 00:21:56,800 If you recall from our video on dynamic memory allocation, 439 00:21:56,800 --> 00:21:58,650 that's not very good thing. 440 00:21:58,650 --> 00:22:00,810 >> So as I said, there are several operations 441 00:22:00,810 --> 00:22:04,010 that we need to use to work with linked list effectively. 442 00:22:04,010 --> 00:22:08,430 And you may have noticed I omitted one, deleting a single element from a linked 443 00:22:08,430 --> 00:22:09,064 list. 444 00:22:09,064 --> 00:22:10,980 The reason I did that is it's actually kind of 445 00:22:10,980 --> 00:22:14,360 tricky to think about how to delete a single element from a singly 446 00:22:14,360 --> 00:22:15,600 linked list. 447 00:22:15,600 --> 00:22:19,950 We need to be able to skip over something in the list, which 448 00:22:19,950 --> 00:22:22,975 means we get to a point-- we want to delete this node-- 449 00:22:22,975 --> 00:22:25,350 but in order to make it so we don't lose any information, 450 00:22:25,350 --> 00:22:30,530 we need to connect this node over here, here. 451 00:22:30,530 --> 00:22:33,390 >> So I probably did that wrong from a visual perspective. 452 00:22:33,390 --> 00:22:36,830 So we're at the beginning of our list, we're proceeding through, 453 00:22:36,830 --> 00:22:40,510 we want to delete this node. 454 00:22:40,510 --> 00:22:43,440 If we just delete it, we've broken the chain. 455 00:22:43,440 --> 00:22:45,950 This node right here refers to everything else, 456 00:22:45,950 --> 00:22:48,260 it contains the chain from here on out. 457 00:22:48,260 --> 00:22:51,190 >> So what we need to do actually after we get to this point, 458 00:22:51,190 --> 00:22:56,670 is we need to step back one, and connect this node over to this node, 459 00:22:56,670 --> 00:22:58,590 so we can then delete the one in the middle. 460 00:22:58,590 --> 00:23:02,120 But singly linked lists don't provide us a way to go backwards. 461 00:23:02,120 --> 00:23:05,160 So we need to either keep two pointers, and move them 462 00:23:05,160 --> 00:23:09,527 sort of off step, one behind the other as we go, or get to a point 463 00:23:09,527 --> 00:23:11,110 and then send another pointer through. 464 00:23:11,110 --> 00:23:13,150 And as you can see, it can get a little messy. 465 00:23:13,150 --> 00:23:15,360 Fortunately, we have another way to resolve that, 466 00:23:15,360 --> 00:23:17,810 when we talk about doubly linked lists. 467 00:23:17,810 --> 00:23:20,720 >> I'm Doug Lloyd, this is CS50. 468 00:23:20,720 --> 00:23:22,298 40887

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.