CSCI 104 Linked Lists: Mark Redekopp David Kempe
CSCI 104 Linked Lists: Mark Redekopp David Kempe
CSCI 104
Linked Lists
Mark Redekopp
David Kempe
2
Array Problems
• Once allocated an array cannot grow or shrink
• If we don't know how many items will be added we could just allocate an
array larger than we need but…
– We might waste space
– What if we end up needing more…would need to allocate a new array and
copy items
• Arrays can't grow with the needs of the client
21
append(21) =>
0 1 2 3 4 5
Old, full array 30 51 52 53 54 10
0 1 2 3 4 5 6 7 8 9 10 11
Allocate new
array
0 1 2 3 4 5 6 7 8 9 10 11
Copy over items 30 51 52 53 54 10
0 1 2 3 4 5 6 7 8 9 10 11
Add new item 30 51 52 53 54 10 21
3
Linked List
• Use structures/classes and pointers #include<iostream>
using namespace std;
to make ‘linked’ data structures
struct Item {
• A List is… int val; Item blueprint:
Item* next; int Item*
– Arbitrarily sized collection of }; val next
values class List
– Can add any number of new values {
public:
via dynamic memory allocation List();
~List();
– Supports typical List ADT void push_back(int v); ...
operations: private:
Item* head_;
• Insert };
• Get
• Remove
• Size head 0x148
0x148 0x1c0 0x168
• Empty 0x0
3 0x1c0 9 0x168 2 (Null)
• Can define a List class val next val next val next
A Common Misconception
• Important Note:
– 'head' is NOT an Item, it is a pointer to the
first item
– Sometimes folks get confused and think
head is an item and so to get the location
of the first item they write 'head->next' head
– In fact, 'head->next' evaluates to the 2nd 0x148
items address
0x148 0x1c0 0x168
0x0
3 0x1c0 9 0x168 2 (Null)
val next val next val next
8
Append
#include<iostream>
using namespace std;
• Adding an item (train car) to the struct Item {
int val;
back can be split into 2 cases: Item* next;
};
– Attaching the car to the engine (i.e.
void append(Item*& head, int v)
the list is empty and we have to {
change the head pointer) if(head == NULL){
head = new Item;
– Attaching the car to another car (i.e. }
head->val = v; head->next = NULL;
head1
0x148
0x0 0x148
3 NULL
val next
9
Linked List
#include<iostream>
head
Linked List
#include<iostream>
• Adding an item (train car) to the using namespace std;
struct Item {
back can be split into 2 cases: int val;
Item* next;
};
– Attaching the car to the engine (i.e.
the list is empty and we have to void append(Item*& head, int v)
{
change the head pointer) if(head == NULL){
head = new Item;
– Attaching the car to another car (i.e. head->val = v; head->next = NULL;
}
the list has other Items already) and else {...}
so we update the next pointer of an }
head
Append()
void append(Item*& head, int v)
• Look at how the head parameter is {
Item* newptr = new Item;
passed…Can you explain it? newptr->val = v; newptr->next = NULL;
Append()
void append(Item*& head, int v)
0x148 0x1c0
temp temp
started }
temp->next = newptr;
}
• How do we take a step }
– temp = temp->next;
0x0
3 0x1c0 9 NULL
val next val next
0x148 0x1c0
temp temp
15
head2 0x1c0
Head Recursion
• Recurse to the end of the chain (head == NULL) and then start
summing on the way back up
– What should the base case return
– What should recursive cases (normal nodes) return?
Main()
head 0x148
Tail Recursion
• Produce sum as you walk down the list then just
return the final answer back up the list
Main()
head 0x148
14 14 14 14
Exercises
• llsum_head
• llsum_tail
24
Recursive Copy
• How could you make a copy of a linked list using
recursion struct Item {
int val;
0x148
Item* next;
oldhead 0x148 0x1c0
Item(int v, Item* n){
0x0 val = v; next = n;
3 0x1c0 9 NULL
}
val next val next };
}
}
int main()
newhead ??? { Item* oldhead, *newhead;
...
newhead = copyLL(oldhead);
}
25
Recursive Copy
• How could you make a copy of a linked list using
recursion
struct Item {
oldhead 0x148 0x148 0x1c0 int val;
0x0 Item* next;
3 0x1c0 9 NULL Item(int v, Item* n){
val next val next
val = v; next = n;
}
};
Recursive Copy
• How could you make a copy of a linked list using
recursion
struct Item {
oldhead 0x148 int val;
Item* next;
0x148 0x1c0 Item(int v, Item* n){
0x0 val = v; next = n;
3 0x1c0 9 NULL }
val next val next
};
INCREASING EFFICIENCY OF
OPERATIONS + DOUBLY LINKED
LISTS
28
Removal
• To remove the last item, we need to update the 2nd
to last item (set it's next pointer to NULL)
• We also need to update the tail pointer
• But this would require us to traverse the full list
• ONE SOLUTION: doubly-linked list
tail
0x1c0
head
…
0x148 0x200 0x1c0
0x148
3 0x200 5 0x1c0 9 NULL
Doubly-Linked Lists
• Includes a previous pointer #include<iostream>
be NULL
tail
0x210
head
0x148 0x1c0 0x210
0x148
NULL 3 0x1c0 0x148 9 0x210 0x1c0 6 NULL
0x190
head
12
0x148
prev val next
head
0x148
prev val next prev val next prev val next prev val next
33
0x190
head 12
head
0x148
prev val next prev val next prev val next prev val next
35
head
0x148
head 0x1c0