260 likes | 280 Views
CS 240: Data Structures. Thursday, June 21 th Lists – Array based, Link based Dynamic vs Static. Lists. Here is a “random access” list, in array form. Lists. Here is a “traditional” list, in array form Wait…. Where do we start? We have to maintain that data separately.
E N D
CS 240: Data Structures Thursday, June 21th Lists – Array based, Link based Dynamic vs Static
Lists • Here is a “random access” list, in array form
Lists • Here is a “traditional” list, in array form • Wait…. Where do we start? • We have to maintain that data separately. • We usually refer to it as “first” • first = i+20
Implications • How is the data being accessed? • ??? • These are perfect candidates to use with pointers.
What is a list? • A list is a container class • Like an array • However… • The list includes: • 1) The address of the first piece of data • 2) The data • 3) For each data, the address of the next piece.
List Data Since each data is attached to the location of the next piece we can represent them as an ADT: We generally refer to this as a Node class Node { T thedata; //Remember, T can be any type memory_address next_data; Node * next_data; }; Ok, Node has our data. What about “memory_address”? Well, Node tells us where the next Node is…. Therefore, memory_address is really a Node pointer.
Floating Nodes • Now we have a node (instead of separate data): Address: ? Address: ? Type: Unknown (T) Value (X bits): ? ADT: Node Size: X+32 bits thedata: (X bits) -> T next_node (32 bits) -> Node * Address: ? Type: Node * Value (32 bits): ? Bonus: Instead of having to keep track of two pieces of data, we keep track of one! If we know where the node is, we know where the data and next_node pointer are!
Floating Nodes • Ok, we can create a node now. • First, we should decide what kind of data node will hold. • Later, we will make it possible for node to hold anything (a couple of weeks from now). Address: 0xABCD ADT: Node Size: X+32 bits thedata: (X bits) -> T next_node (32 bits) -> Node *
Floating Nodes • Strings sound good. • For ease, we will directly access the elements of Node in these slides. We can also write methods to place the data and change the pointers. Address: 0xABCD ADT: Node Size: X+32 bits thedata: (32 bits) -> String next_node (32 bits) -> Node *
Floating Nodes class Node { public: string thedata; Node * next_data; }; Address: 0xABCD ADT: Node Size: X+32 bits thedata: (32 bits) -> String next_node (32 bits) -> Node *
Creating a Node • Remember, we need to know where the first node in our list is. • Therefore: “Node * first = new Node();” • Remember to delete it when you are done! first - Address: 0x50F4 ADT: Node Size: X+32 bits thedata: (32 bits) -> String next_node (32 bits) -> Node *
Storing Data • For some string we’ll call “userinput” with value “apple” • first->thedata = userinput; • first->next_node = NULL; first - Address: 0x50F4 ADT: Node Size: X+32 bits thedata: (32 bits) -> String next_node (32 bits) -> Node * ADT: Node Size: X+32 bits thedata: (32 bits) -> String “apple” next_node (32 bits) -> Node * NULL
Adding Data • How do we add data? • Well, we have to find an empty location in our list. • Access the list and search for an empty location!. first - Address: 0x50F4 ADT: Node Size: X+32 bits thedata: (32 bits) -> String “apple” next_node (32 bits) -> Node * NULL
Adding Data • Let’s add “donut”. • first->next_node = new Node(); • Node * accessptr = first->next_node; first - Address: 0x50F4 ??? - Address: 0x846c ADT: Node Size: X+32 bits thedata: (32 bits) -> String “apple” next_node (32 bits) -> Node * NULL ADT: Node Size: X+32 bits thedata: (32 bits) -> String “apple” next_node (32 bits) -> Node * 0x846c ADT: Node Size: X+32 bits thedata: (32 bits) -> String Uninitialized next_node (32 bits) -> Node * Uninitialized
Adding Data • Node * accessptr = first->next_node; • accessptr->thedata = “donut”; • accessptr->next_node = NULL; first - Address: 0x50F4 ??? - Address: 0x846c ADT: Node Size: X+32 bits thedata: (32 bits) -> String “apple” next_node (32 bits) -> Node * 0x846c ADT: Node Size: X+32 bits thedata: (32 bits) -> String Uninitialized next_node (32 bits) -> Node * Uninitialized ADT: Node Size: X+32 bits thedata: (32 bits) -> String “donut” next_node (32 bits) -> Node * NULL
This can get much larger first: 0x50F4 0x3120 0x8458 ADT: Node Size: X+32 bits thedata: “apple” next_node: 0x846c ADT: Node Size: X+32 bits thedata: “cashew” next_node: 0x4278 ADT: Node Size: X+32 bits thedata: “hat” next_node: NULL Organizing this will allow us to make something useful! 0x4278 0x846c 0x5610 ADT: Node Size: X+32 bits thedata: “tomato” next_node: 0x5610 ADT: Node Size: X+32 bits thedata: “donut” next_node: 0x3120 ADT: Node Size: X+32 bits thedata: “banana” next_node: 0x8458
Why lists? • So far, all we have done is manage items using contiguous memory. • If we needed more room, we would ask for it and copy all of our data into the larger space. Movin on up!
Contiguous Memory • So, what’s the big deal? • Isn’t moving up good? • Of course! But it is expensive! • We don’t want to try to hold everything! It gets messy!
The Collector • Using our “mycontainer”, our CDs wouldn’t be very organized. • If we organize when we insert….
Insertion Issues • When can insertion be a problem? • Inserting at the end of the mycontainer is easy! • Inserting in the middle isn’t too bad! • Inserting at the front…. • With a list, we can insert easily!
Let us represent this list: first: 0x50F4 0x3120 0x8458 ADT: Node Size: X+32 bits thedata: “apple” next_node: 0x846c ADT: Node Size: X+32 bits thedata: “cashew” next_node: 0x4278 ADT: Node Size: X+32 bits thedata: “hat” next_node: NULL 0x4278 0x846c 0x5610 ADT: Node Size: X+32 bits thedata: “tomato” next_node: 0x5610 ADT: Node Size: X+32 bits thedata: “donut” next_node: 0x3120 ADT: Node Size: X+32 bits thedata: “banana” next_node: 0x8458
Nodes • A node’s pointer nodes to 1 of 2 places: • To another node • To Null • We can additional pointers in our Node and maintain additional data for various reasons.
List Construction • To create a list: • We need to create a node pointer (which points to Null) • Is that it? • Well, we need functions to act on the list. • Some things – like size – may be easier to manage as part of the list.
List Insertion • Inserting into the list has two cases: • The list was empty: • The list was not empty: • However, our insertion policy may make this more difficult: • Just insert • Insert in order • This technically doesn’t add another case
List Removal • If the value is in the list, removing a value requires that we ensure the list is still valid: Start 56 60 72 80 90 Null Now, lets remove 80. Ok, let’s traverse the list! That’s not good.
List Removal • Let’s try this again. Start 56 60 72 80 90 Null Now, lets remove 80. Ok, let’s traverse the list! He made it!