CS 112
Introduction to Data Structures
Week 06
Linked Lists
Eric Araújo
Calvin University · Fall 2026
Node and List classesprepend and appendappend() when full: allocate, copy everything, deleteinsert() in the middle: shift every element after itremove(): shift everything back downStore the data in chunks instead of one block. Inserting then only shifts within a chunk.
nullptr, which is how you know you've reached the end.
class Node {
public:
Node();
Node(Item it, Node *nxt);
~Node();
Item myItem;
Node *myNext;
};
class List {
public:
List();
~List();
void prepend(Item it);
void append(Item it);
private:
unsigned mySize;
Node *myFirst;
Node *myLast;
};
List. Node is an implementation detail, which is exactly what private is for.
Node *current = myFirst;
while (current != nullptr) {
cout << current->myItem << endl;
current = current->myNext; // hop to the next
}
for (i = 0; i < n; ++i). You will write it
dozens of times, and every one of its bugs comes from forgetting the nullptr test or
forgetting to advance.
void List::prepend(Item it) {
myFirst = new Node(it, myFirst); // point the new one at the old first
if (mySize == 0) { myLast = myFirst; }
++mySize;
}
prepend() need that if (mySize == 0)?
mySize correctmyLast is never usedmyFirst and myLast must end up pointing at the new node. Miss it and myLast stays nullptr, which breaks the very next append(). Empty and single-element lists are where linked-list bugs live.
myLast?
void List::append(Item it) {
Node *n = new Node(it, nullptr);
if (mySize == 0) {
myFirst = myLast = n;
} else {
myLast->myNext = n; // old last points at n
myLast = n;
}
++mySize;
}
myLast you'd walk the whole list to find the end, linear. Storing one extra pointer makes append() constant. A little memory buys a lot of speed.
Node::~Node() {
delete myNext; // destroy the rest of the list
}
List::~List() {
delete myFirst; // starts the chain
}
Deleting the first Node runs its destructor, which deletes the second, which deletes the third…
delete nullptr is harmless and defined; that's what stops the chain at the end.
Elegant, but on a very long list it also means a very deep stack of destructor calls.
List holding 4 items goes out of scope. How many Node destructors run?
~List deletes myFirst; each ~Node deletes the one after it. The chain stops when it reaches nullptr, which is not a node and needs no destructor.
Walking a list, one hop at a time.
(the list is fine. the loop is forever.)
| Operation | Dynamic array | Linked list |
|---|---|---|
index v[i] | constant | linear |
| append | amortized constant | constant |
| prepend | linear | constant |
| insert in middle | linear | linear to find, constant to link |
| remove | linear | linear to find, constant to unlink |
| traverse all | linear | linear |
| memory per item | just the item | item + a pointer |
Node holds an item and the address of the nextwhile (current != nullptr): advance or loop foreverprepend and append are constant; indexing is lineardelete nullptr ends the chain safely
This deck stands on earlier CS112 materials by
Joel Adams and Victor Norman · adapted and extended by Eric Araújo