 Good morning and welcome to James Madison University in the beautiful fall time of year when the leaves are changing color and the sunrises are getting better. This week we're going to take a look at data structures. Now there's a few things that you should notice as you look through the material in this chapter and also do the exercises in the lab. One is that humans like to think of data organized in many different ways. We think of things like people lining up in a queue. We think of stacking up data in a pile. We think about trees and we think about other structures that you'll learn about in CS 240. But the computer only thinks about data in one way. You give me a memory address, I'll give you the value. So let's learn how to build abstract tools that make use of this computer's way of thinking about data so that we can actually support a human being's way of thinking about the data. A couple patterns you'll notice is that any data structure has two flavors. It can be a contiguous set of data or it can be a linked structure. The book also uses the term static and dynamic to describe these two concepts. I'd also like to introduce you to how Python models data using built-in structures like lists and tuples and what the difference are between those two data types. So without further ado, let's get started. Let's say I'd like to have a list of lucky numbers. 7, 3, 25, 1, and 15. Now as we discussed in class, the way to make a list in Python is using brackets and you can put any elements between the brackets separated by commas. Now today I'm running Python in a special environment that visualizes each line of code as I type it. So on the right I have a web browser that's using the modules that you can download from onlinepythontutor.com and on the left I have a Python terminal where I type my commands. Now here's this list. Notice the value of the variable lucky. The value of that variable is not a list but rather a pointer to a list somewhere else in memory. So as we'll talk about later this week, these object types have a level of indirection rather than being stored directly at the location of this variable. I'm storing a location of somewhere else in memory and then these values are all stored contiguously in those memory slots. Now speaking of memory slots, notice what happens when I print lucky sub 1. It's actually not the first item in the list but the second because the indexes start from 0 to 4. Likewise if I try to print the fifth item I'll get an error because 5 is out of this range of indices 0 through 4. Now you can change items in the list using assignment. So let's say I'm going to change the second value which is actually the third value to the message high. Now we'll see in the second or rather the third slot of the list the value high. You can also add elements to the list using the append method. So let me type lucky.append and I'll append. Let's just append the integer 99. Now when I run that I have to scroll over here to actually see that element off the edge given the small resolution of my video recording here. Now we talked about stacks today and in Python you can implement stacks using lists and you can use the append method to push items on the stack and the pop method to get an item off the top of the stack. So for example I could say the top item is lucky.pop. Now when I push enter you'll see top now has the value 99 stored in the memory location for top and that 99 is no longer in the list. In fact let me run that exact same command again. You'll see top is now 15, top is 1, top is high, top is 3. So the interesting thing is here you have a value that's stored directly in memory and here you have a pointer to something else stored in memory. Let me pop it one more time so you can see that I have this empty list. So that's actually kind of boring. Let me append some more things to this list. Let's append the num, let's see here. Now let's do numbers 1.5, oops I did top.append. You can't append anything to an integer. Let me say lucky instead. Lucky.append 1.5, lucky.append, negative 3, lucky.append. What's another good number? How about 101? And lucky.append 74. All right so there's some numbers. Let me show you some more things you can do with lists. I can sort them if I just call the sort function. Now watch what happens to these numbers when I push enter. You'll notice that I actually sorted the list in place. In other words I changed all the numbers in the same memory location where that list existed but now they're in numerical order. Now you can do the opposite of sorting if you say lucky.reverse. Now they're in reverse numerical order. So these are some of the things that you can do with lists. You can index them using brackets. So if I want the third item in the lucky list I say lucky bracket 2 bracket and the way we pronounce this is sub just like a subscript in mathematics. You can create new lists using assignments and you can use the append and the pop function to add and remove items from the end of a list if you want to treat it like a stack. Oh what if you want to treat it like a queue? That would be lucky.insert. Clear the screen so it's a little bit easier to follow what I'm doing now. So like I was saying if you want to use this as a queue you could use the insert function and the first argument you have to give is where do you want to insert it. So I want to insert at the front of the list I give it element zero and if I want to insert the value one two three when I push enter you'll see one two three is here at the front. Now in general you could insert these wherever you want like if I want to insert it item two four five six you'll notice here on the right item two is now four five six everything else in the list gets shifted over. So in summary if you'd like to use a list as a queue you always insert it zero let's give it the value five and if you want to get the item off the end you say lucky.pop. So in other words the pop function can be used to get an item off a stack or off a queue depending on the context of how you write your code but list is a generic structure that will implement either abstract concept. There's another data structure that you will encounter a lot if you continue to learn Python programming and that is called a tuple. So in this example I want to show you what how a list is different from a tuple and what tuples are useful for. Let me start out by making an employee structure and I'm going to use the list that we did before. Let's say that this employee's name is Alex and Alex is making seven dollars and eighty one cents per hour at this job and so what you'll see on the right is we have a list with these two elements in the list. Now a tuple is exactly the same as a list in terms of syntax but you use parentheses instead of brackets. Now watch what happens over here on the left as I change this to a tuple sorry meant to say the right. A tuple is displayed here for the data type and notice how this is drawn as a rectangle. It's closed on all four sides. So again let me change it back to a list. You'll see how the list is open and I change it back to a tuple and now it's closed. The basic idea is that lists are dynamic immutable. Now we learn about dynamic and static in the book. Dynamic means it can grow. Static means that it's a fixed size. It's not going to change shape. In addition in Python it takes it one step further. List you can change the elements tuples you cannot. Let me show you an example of that. If we want to change this employee's salary for example let me just pull this up. I can say let's see here the first element. If I print that out it's 781 but if I try to change this now to one let's say give them a raise 7, 8, 12 it's going to say sorry tuples do not support item assignment. Once you create a tuple of something you can't change it. Now I could just make a new tuple. I could say alex equals 899 for example and that's just fine. But tuples are immutable and we'll see here in a little bit why that's important. Let me go ahead and create a couple more example tuples like Barb. She's making $9.12 and we'll create a third employee Cody and he's making $7.25 which I guess is minimum wage. And so you'll notice we've got all three of these tuples sitting out here in memory and just like lists tuples are reference types so we have restoring the address of the tuple in the variable that refers to it. So for example if I say x equals m for 2 I basically have two variables that are pointing to the same item in memory. So that's why x sub 0 is the same as employee 2 sub 0 oops. So we've got Barb for x sub 0 and Barb for employee 2 sub 0. Now the interesting thing is when you start to combine these into lists let's say I want to create a company and a company is a list of all my employees and now what we have is this little bit of spaghetti on the right. Company is a list and so I have a pointer to where that list is stored in memory and each element in this list is a tuple which is already stored in memory somewhere else. So these arrows end up pointing to the same place in memory where those tuples exist. I could say print company sub 2 which should be employee 3 codey 725 is part of the output and because company is a list I could change this I could say company sub 2 equals company sub 1 and now what I have is two arrows pointing to the same place in the company. So if I were to print out the entire company I've got Alex Barb and Barb all part of that list. So notice how the syntax is nested here. We've got a bracket for the list and then each tuple in the list is in parentheses and you can compose lists and tuples or lists of lists to get different types of structures. In fact let's take a look at a two-dimensional array or a 2D list or some people call these a matrix in the next segment. So on page 348 it starts to talk about homogeneous arrays and how to look at a two-dimensional array in row major order. Let's do one of those real quick. Let's say I want to have a list of numbers and to make it two-dimensional I actually need a list of lists. So I'm going to start typing a list on that line and I'm going to type one row at a time now. Let's say I have 1, 2, 3 on that row and then I have 4, 5, 6 on that row and 7, 8 and 9. Now each one of these rows is a list and at the end of this list of lists, see I have an open bracket here I'm going to need to type one more bracket there and now look what I've done. When you look at this picture on the right this two-dimensional structure that looks like a tic-tac-toe grid or spreadsheet or something is actually a list of lists. So the first list is 1, 2, 3, the second list is 4, 5, 6 and the third list is 7, 8 and 9. This is using two levels of indirection. The address that's stored in nums which is my variable is a pointer to the first list and that list is actually a list of pointers to other lists and that's actually what we see here on the left. Each one of these lists has to be stored in a separate place of memory because of the way that this language is designed. Now if I actually want to print those things out using row major order let's say I go to the first row and I go to the second column. Now of course the first row is the second row in real life and the second column is the third value 6. So if I go ahead and print, sorry, if I want to print numbers at that row in that column that's what actually gives me the value 6. Now notice I'm using the brackets twice here. The first one is for the row and the second one is for the column. So that's how two-dimensional arrays work in Python and it doesn't have to deal with the address polynomial like in other languages. I'm using that term on page 350 because it just knows to go to this pointer and then go to the other pointer. When you go on to study data structures later in the curriculum you'll learn how to build these abstract tools and that's really the interesting part of data structures is learning how to implement classes that support all of these abstract operations that we've seen visualized today. I think you'll agree that pointers are the meat of all of this. Being able to use a pointer effectively is what allows us to abstract away the details of the machine array representation and be able to provide things like oh this is my left child and this is my right child when thinking about a tree. So hopefully you've learned a little bit today about data structures both theoretically and also practically how to use them in the Python language and also you've grown a little bit of appreciation for why pointers are so important in computing. With that hopefully you'll spend some time on PythonTutor and tomorrow's lab will even be more engaging. We'll see you then.