Data Structures: Crash Course Computer Science #14
CrashCourse
0:03 Hi, I'm Carrie Anne, and welcome to Crash Course Computer Science!
0:05 Last episode, we discussed a few example classic algorithms,
0:08 like sorting a list of numbers
0:09 and finding the shortest path in a graph.
0:11 What we didn’t talk much about,
0:13 is how the data the algorithms ran on was stored in computer
0:16 memory.
0:16 You don’t want your data to be like John Green’s college dorm room,
0:19 with food, clothing and papers strewn everywhere.
0:21 Instead, we want our data to be structured,
0:23 so that it’s organized, allowing things
0:25 to be easily retrieved and read.
0:27 For this, computer scientists use Data Structures!
0:29 INTRO We already introduced one basic data structure last episode,
0:42 Arrays, also called lists or
0:43 Vectors in some languages.
0:45 These are a series of values stored in memory.
0:47 So instead of just a single value being saved into a variable,
0:50 like ‘j equals 5’, we
0:51 can define a whole series of numbers, and save that into an array variable.
0:55 To be able to find a particular value in this array,
0:58 we have to specify an index.
0:59 Almost all programing languages start arrays at index 0,
1:02 and use a square bracket syntax
1:04 to denote array access.
1:05 So, for example,
1:06 if we want to add the values in the first and third spots of our array
1:10 ‘j’, and save that into a variable ‘a’, we would write a line of code like this.
1:14 How an array is stored in memory is pretty straightforward.
1:16 For simplicity,
1:17 let’s say that the compiler chose to store ours at memory location 1,000.
1:21 The array contains 7 numbers,
1:23 and these are stored one after another in memory, as seen here.
1:26 So when we write “j index of 0”,
1:28 the computer goes to memory location 1,000, with an offset
1:31 of 0, and we get the value 5.
1:33 If we wanted to retrieve “j index of 5”,
1:36 our program goes to memory location 1000,
1:38 plus an offset of 5, which in this case, holds a value of 4.
1:42 It’s easy to confuse the fifth number in the array with the number at index 5.
1:45 They are not the same.
1:46 Remember,
1:46 the number at index 5 is the 6th number in the array because the first number
1:50 is at index 0.
1:51 Arrays are extremely versatile data structures,
1:53 used all the time, and so there are many functions
1:55 that can handle them to do useful things.
1:57 For example,
1:58 pretty much every programming language comes with a built-in sort function,
2:01 where you just pass in your array, and it comes back sorted.
2:04 So there’s no need to write that algorithm from scratch.
2:06 Very closely related are Strings,
2:08 which are just arrays of characters, like letters, numbers,
2:11 punctuation and other written symbols.
2:13 We talked about how computers store characters way back in Episode 4.
2:16 Most often, to save a string into memory, you just put it in quotes, like so.
2:20 Although it doesn’t look like an array, it is.
2:23 Behind the scenes, the memory looks like this.
2:24 Note that the string ends with a zero in memory.
2:27 It’s not the character zero, but the binary value 0.
2:31 This is called the null character, and denotes the end of the string in memory.
2:34 This is important because if I call a function like “print quote”,
2:37 which writes the string
2:38 to the screen,
2:39 it prints out each character in turn starting at the first memory location,
2:42 but it needs to know when to stop!
2:44 Otherwise, it would print out every single thing in memory as text.
2:47 The zero tells string functions when to stop.
2:50 Because computers work with text so often,
2:52 there are many functions that specifically
2:54 handle strings.
2:55 For example,
2:55 many programming languages have a string concatenation function, or “strcat”,
2:59 which takes in two strings, and copies the second one to the end of the first.
3:03 We can use arrays for making one dimensional lists,
3:05 but sometimes you want to manipulate
3:07 data that is two dimensional,
3:08 like a grid of numbers in a spreadsheet, or the pixels
3:11 on your computer screen.
3:12 For this, we need a Matrix.
3:14 You can think of a Matrix as an array of arrays!
3:17 So a 3 by 3 matrix is really 2 an array of size 3,
3:20 with each index storing an array of
3:21 size 3.
3:23 We can initialize a matrix like so.
3:24 In memory, this is packed together in order like this.
3:27 To access a value, you need to specify two indexes,
3:30 like “J index of 2, then index
3:32 of 1”- this tells the computer you’re looking for
3:35 the item in subarray 2 at position 1.
3:37 And this would give us the value 12.
3:39 The cool thing about matrices is we’re not limited
3:40 to 3 by 3— we can make them any
3:42 size we want— and we can also make them any number of dimensions we want.
3:46 For example, we can create a five dimensional matrix and access it like this.
3:50 That’s right,
3:50 you now know how to access a five dimensional matrix— tell your friends!
3:54 So far,
3:55 we’ve been storing individual numbers or letters into our arrays or matrices.
3:59 But often it’s useful to store a block of related variables together.
4:02 Like, you might want to store a bank account number along with its balance.
4:05 Groups of variables like these can be bundled together into a Struct.
4:09 Now we can create variables that aren’t just single numbers,
4:11 but are compound data
4:12 structures, able to store several pieces of data at once.
4:16 We can even make arrays of structs that we define,
4:18 which are automatically bundled together
4:20 in memory.
4:21 If we access, for example, J index of 0,
4:23 we get back the whole struct stored there, and
4:25 we can pull the specific account number and balance data we want.
4:28 This array of structs, like any other array,
4:30 gets created at a fixed size that can’t
4:32 be enlarged to add more items.
4:34 Also, arrays must be stored in order in memory,
4:36 making it hard to add a new item to the middle.
4:38 But, the struct data structure can be used
4:41 for building more complicated data structures
4:42 that avoid these restrictions.
4:44 Let’s take a look at this struct that’s called a “node”.
4:46 It stores a variable, like a number, and also a pointer.
4:49 A pointer is a special variable that points,
4:51 hence the name, to a location in memory.
4:53 Using this struct, we can create a linked list,
4:56 which is a flexible data structure that
4:57 can store many nodes.
4:59 It does this by having each node point to the next node in the list.
5:02 Let’s imagine we have three node structs saved in memory,
5:06 at locations 1000, 1002 and 1008.
5:09 They might be spaced apart,
5:10 because they were created at different times, and other data
5:13 can sit between them.
5:14 So, you see that the first node contains the value 7,
5:17 and the location 1008 in its “next”
5:19 pointer.
5:20 This means that the next node in the
5:22 linked list is located at memory location 1008.
5:24 Looking down the linked list, to the next node,
5:26 we see it stores the value 112 and points
5:28 to another node at location 1002.
5:31 If we follow that,
5:32 we find a node that contains the value 14 and points back to the first
5:36 node at location 1000.
5:37 So this linked list happened to be circular,
5:39 but it could also have been terminated by
5:41 using a next pointer value of 0— the
5:43 null value— which would indicate we’ve reached
5:45 the end of the list.
5:47 When programmers use linked lists,
5:48 they rarely look at the memory values stored in the next
5:50 pointers.
5:51 Instead, they can use an abstraction of a linked list,
5:53 that looks like this, which is
5:55 much easier to conceptualize.
5:56 Unlike an array, whose size has to be pre-defined,
5:59 linked lists can be dynamically extended or
6:01 shortened.
6:02 For example, we can allocate a new node in memory,
6:04 and insert it into this list, just
6:06 by changing the next pointers.
6:07 Linked Lists can also easily be re-ordered, trimmed, split, reversed, and so on.
6:12 Which is pretty nifty!
6:13 And pretty useful for algorithms like sorting, which we talked about last week.
6:16 Owing to this flexibility,
6:17 many more-complex data structures are built on top of linked lists
6:21 The most famous and universal are queues and stacks.
6:23 A queue– like the line at your post office– goes in order of arrival.
6:27 The person who has been waiting the longest, gets served first.
6:30 No matter how frustrating it is that all you want
6:31 to do is buy stamps and the person in
6:33 front of you seems to be mailing 23 packages.
6:36 But, regardless, this behavior is called First-In First-Out, or FIFO.
6:39 That’s the first part.
6:41 Not the 23 packages thing.
6:42 Imagine we have a pointer, named “post office queue”,
6:45 that points to the first node in
6:46 our linked list.
6:47 Once we’re done serving Hank,
6:49 we can read Hank’s next pointer, and update our “post
6:51 office queue” pointer to the next person in the line.
6:54 We’ve successfully dequeued Hank— he’s gone, done, finished.
6:58 If we want to enqueue someone, that is,
6:59 add them to the line, we have to traverse down
7:02 the linked list until we hit the end,
7:03 and then change that next pointer to point to
7:05 the new person.
7:06 With just a small change, we can use linked lists as stacks, which are LIFO…
7:10 Last-In First-Out.
7:11 You can think of this like a stack of pancakes...
7:13 as you make them, you add them to the top
7:15 of stack.
7:16 And when you want to eat one, you take them from the top of the stack.
7:19 Delicious!
7:20 Instead of enqueueing and dequeuing,
7:21 data is pushed onto the stack and popped from the stacks.
7:25 Yep, those are the official terms!
7:27 If we update our node struct to contain not just one,
7:30 but two pointers, we can build trees,
7:32 another data structure that’s used in many algorithms.
7:34 Again, programmers rarely look at the values of these pointers,
7:37 and instead conceptualize trees like this: The top most node is called the root.
7:42 And any nodes that hang from other nodes are called children nodes.
7:45 As you might expect, nodes above children are called parent nodes.
7:48 Does this example imply that Thomas Jefferson is the parent of Aaron Burr?
7:51 I’ll leave that to your fanfiction to decide.
7:54 And finally,
7:54 any nodes that have no children— where the tree ends— are called Leaf Nodes.
7:58 In our example, nodes can have up to two children,
8:01 and for that reason, this particular data
8:03 structure is called a binary tree.
8:04 But you could just as easily have trees with three,
8:07 four or any number of children by modifying
8:09 the data structure accordingly.
8:10 You can even have tree nodes that use linked
8:12 lists to store all the nodes they point to.
8:15 An important property of trees– both in real
8:16 life and in data structures– is that
8:18 there’s a one-way path from roots to leaves.
8:20 It’d be weird if roots connected to leaves, that connected to roots.
8:23 For data that links arbitrarily, that include things like loops,
8:26 we can use a graph data
8:28 structure instead.
8:29 Remember our graph from last episode of cities connected by roads?
8:32 This can be stored as nodes with many pointers,
8:34 very much like a tree, but there is no notion
8:36 of roots and leaves, and children and parents…
8:38 Anything can point to anything!
8:40 So that’s a whirlwind overview of pretty
8:42 much all of the fundamental data structures
8:43 used in computer science.
8:45 On top of these basic building blocks,
8:47 programmers have built all sorts of clever variants, with
8:49 slightly different properties— data structures like red-black trees and heaps,
8:52 which we don’t have time to cover.
8:54 These different data structures have properties
8:56 that are useful for particular computations.
8:59 The right choice of data structure can make your job a lot easier,
9:01 so it pays off to think
9:02 about how you want to structure your data before you jump in.
9:05 Fortunately, most programming languages come with libraries
9:08 packed full of ready-made data structures.
9:10 For example, C++ has its Standard Template Library,
9:13 and Java has the Java Class Library.
9:15 These mean programmers don’t have to
9:17 waste time implementing things from scratch,
9:19 and
9:19 can instead wield the power of data structures to do more interesting things,
9:24 once again allowing us to operate at a new level of abstraction!
9:27 I’ll see you next week.