Abstract Data Types (Simulated)

Linked List

A chain of nodes where each node points to the next — simulated with two arrays (data + pointer), a start pointer and a free list. Traverse to find an item, insert by taking a node from the free list, and delete by re-linking pointers. The ADT behind dynamic lists where data never moves.

19.1 What is a Linked List?

An array keeps items in fixed neighbouring slots, so inserting in the middle means shuffling everything along. A linked list solves that. Each item sits in a node that also stores a pointer to where the next item is. To insert or remove an item you just change a couple of pointers — the data itself never moves.

Think of a treasure hunt: each clue tells you where the next clue is hidden. You start at the first clue (the start pointer) and follow the trail until a clue says “this is the last one” (a null pointer). Re-routing the hunt is easy — you only rewrite which clue points where.

Since Python has no built-in pointer type, we simulate the list with two arrays: a data array holding the values and a pointer array holding, for each node, the index of the next node. We also keep a free list of unused nodes.

TermMeaning
Linked listA chain of nodes where each node points to the next. Reordered by changing pointers, not by moving data.
NodeOne element: a data value plus a pointer to the next node.
Pointer / next fieldThe index of the next node in the chain.
Null pointerA special value (we use -1) marking the end of the list — there is no next node.
Start pointerThe index of the first node. -1 means the list is empty.
Free listA chain of unused nodes, ready to be taken when inserting. A free pointer marks its start.
TraverseTo step through the list from the start, following each pointer in turn.
Dynamic structureA structure that can grow and shrink at run time by adding/removing nodes.
Key rule — linked list features
  • Each node holds data + a pointer to the next node.
  • A start pointer marks the first node; the last node holds a null pointer.
  • Insert and delete by changing pointers, not by moving data.

Each node is [ data | next pointer ]. Follow the arrows from start.

start
60
1
45
0
88
-1
Ø (null)

last node → null (Ø = -1)

Task — Worked Example — Describe three key features [3 marks]
Describe three key features of a linked list. [3]
Hint:
  • Step 1: What a node contains.
  • Step 2: How the list is entered and how it ends.
  • Step 3: How items are added/removed.
Your Turn — Your Turn — Advantage over an array [2 marks]
Explain one advantage of a linked list over a simple array when inserting a value into the middle. [2]
Hint:
  • Think about what an array has to do to make room.
Exam tip:
  • The phrase examiners reward is “data is added/removed by manipulating pointers, not by moving data,” plus “the last node has a null pointer.”
  • Naming the free list for unused nodes often earns an extra mark.

19.2 Two Arrays and the Free List

Why are we doing this?
  • Mark scheme: “Complete the diagram to show how the linked list is represented using the variables and arrays” is a near-guaranteed Paper 2/3 question (e.g. 9618/22 O/N 2023 Q3).
  • The marks come from reading the start pointer, following the pointer array, and recognising the free list.
  • Master the table and you've cleared the most common linked-list question.

We store the list in two arrays of the same length. The data array holds the values. The pointer array holds, at the same index, the location of the next node. Two variables complete the picture: start (index of the first node) and free (index of the first unused node). Unused nodes are chained together exactly like the list — that chain is the free list.

MAX = 7
data  = [None] * MAX     # the values
nextp = [None] * MAX     # index of the next node
start = -1               # -1 = empty list
free  = 0                # first free node

def setup():
    global start, free
    start = -1
    free = 0
    for i in range(MAX - 1):
        nextp[i] = i + 1      # each free node links to the next
    nextp[MAX - 1] = -1       # last free node -> null

Here is a list of three marks — 60, 45, 88 — stored in the arrays. The start pointer says the first node is at index 2; from there you follow the pointer array.

Indexdatanextprole
088-13rd node → null
14502nd node → index 0
26011st node → index 1
3·4free → 4
4·5free → 5

Read the list by starting at index 2 (60), following nextp: 2 → 1 → 0 → null gives 60, 45, 88. The free list begins at index 3. Pointers: start = 2, free = 3.

Task — Worked Example — State the order and last node [2 marks]
Using the table above, state the order of the data values as the list would be read, and state which index holds the last node. [2]
Hint:
  • Step 1 — follow start: start = 2 → data 60, nextp 1.
  • Step 2 — follow the chain: 1 → data 45, nextp 0; 0 → data 88, nextp -1 (end).
Your Turn — Your Turn — Read a list of names [2 marks]
A linked list of three names is stored with start = 1. The pointer array is: index 0 → -1, index 1 → 3, index 3 → 0. The data array is: 0="Nawal", 1="Adri", 3="Mohar". State the order the names are read. [2]
Hint:
  • Start at index 1, follow each nextp value.

19.2B Interactive Simulator

Try the linked list yourself. Set MAX_SIZE, enter a value, and click Insert Front, Find, or Delete. Step through the pointer moves one at a time, or press Play to watch them run automatically. The free list starts pre-linked — every insert takes a node from it, every delete returns one to it.

Interactive Simulator

Two-Array Representation

start: -1free: 0MAX: 7
Index0123456
data
·
·
·
·
·
·
·
nextp
1
2
3
4
5
6
-1
ptrfree

List chain (follow start)

null (empty)

Status: Choose an operation to begin. The free list is pre-linked.

Code (select an op)

1# Choose Insert, Find, or Delete to see the code highlighted here.

19.3 Traverse and Find

Why are we doing this?
  • Finding an item is the syllabus's named operation for linked lists.
  • The technique — start at start, follow nextp until you match or hit null — is the same loop you'll reuse for delete, so it's worth getting fluent.

To find a value, set a current pointer to start and step along: if the current node's data matches, stop; otherwise move current to nextp[current]. When current becomes -1 you've run off the end without finding it.

def find(target):
    current = start
    while current != -1:          # until we run off the end
        if data[current] == target:
            return current        # found - give its index
        current = nextp[current]  # follow the pointer
    return -1                     # not found
Key rule — traversal loop
  • Start at start; while current != -1, check the data, then move to nextp[current].
  • The null pointer is what stops the loop.
Task — Worked Example — contains(target) [4 marks]
Write program code for a function contains(target) that returns True if the value is in the list and False otherwise. [4]
Hint:
  • Step 1 — start at the start: current = start.
  • Step 2 — loop until null: while current != -1.
  • Step 3 — match or move on: return True on a match, else follow the pointer; return False after the loop.
Your Turn — Your Turn — position(id) [4 marks]
Naib's app stores student IDs in a linked list. Write program code for a function position(id) that returns the index of the node holding id, or -1 if it is not present. [4]
Hint:
  • This is the original find; return the index, not True/False.
Exam tip:
  • The loop condition must be current != -1 (the null check), not a count.
  • Using the null pointer to stop is the whole idea of a linked list, and examiners look for it specifically.

19.4 Insert a Node

Why are we doing this?
  • Insert is a named operation.
  • The marks reward the four pointer moves: take a node off the free list, store the data, point the new node at the rest of the list, and update start.
  • Inserting at the front is the simplest case and the one most often asked.

To insert a value at the front: take the first free node, store the data there, make the new node point to the old start, then move start to the new node. The free pointer moves on to the next free node.

def insert_front(item):
    global start, free
    if free == -1:                 # no free nodes left
        print("List full")
    else:
        new = free                  # take a free node
        free = nextp[free]          # free list moves on
        data[new] = item            # store the data
        nextp[new] = start          # new node points to old start
        start = new                 # start now points to new node
Key rule — insert order
  • Take node from free list → advance free → store data → new node's pointer = old start → start = new node.
  • Never lose the free list.
Task — Worked Example — add_front(value) [5 marks]
Write program code for a procedure add_front(value) that inserts a value at the front of the linked list, or outputs "Full" if there are no free nodes. [5]
Hint:
  • Five moves: check free empty; take node and advance free; store data; set new node's pointer to old start; update start.
Your Turn — Your Turn — add_bookmark(url) [5 marks]
Nazifa keeps a linked list of bookmarks. Write program code for a procedure add_bookmark(url) that inserts a bookmark at the front, or outputs "No space" if the list is full. [5]
Hint:
  • Same five moves, different names.

19.5 Delete a Node

Why are we doing this?
  • Deleting is the third named operation.
  • The idea: find the node, make the previous node point past it, then hand the freed node back to the free list.
  • No data is moved — only pointers change.

We walk the list keeping track of the previous node as well as the current one. When we find the target, the previous node's pointer is set to skip over it. If the target is the very first node, we just move start instead. Finally we link the removed node onto the front of the free list so it can be reused.

def delete(target):
    global start, free
    current = start
    previous = -1
    while current != -1 and data[current] != target:
        previous = current
        current = nextp[current]
    if current == -1:
        return False            # not found
    if previous == -1:
        start = nextp[current]      # delete the first node
    else:
        nextp[previous] = nextp[current]   # bypass the node
    nextp[current] = free           # return node to free list
    free = current
    return True
Key rule — delete by re-linking
  • Find the node (tracking previous).
  • Point previous past it (or move start if it's first).
  • Then attach the freed node to the free list.
  • The data stays put; only pointers change.
Task — Worked Example 10.3B — Trace the chain
Trace the chain. start = 2; nextp: 2→0, 0→4, 4→-1. What order are the indices visited?
Hint:
  • current = 2; visit 2, follow nextp to 0; visit 0, follow nextp to 4; visit 4, follow nextp to -1 (stop).
Your Turn — Your Turn 10.3B — Trace the chain
Trace the chain. start = 3; nextp: 3→1, 1→5, 5→2, 2→-1. What order are the indices visited?
Hint:
  • Start at 3, follow each pointer to null.
Task — Worked Example 10.3C — is_empty()
Write a function is_empty() for the linked list.
Hint:
  • The list is empty exactly when start is the null pointer.
Your Turn — Your Turn 10.3C — count_nodes()
Write a function count_nodes() that returns how many nodes are in the list.
Hint:
  • Traverse and add one each step.

19.6 Full Exam-Style Question

Paper 3/4 — Section 19.1 · Linked List ADT
  • A program at moshikur.com stores a linked list of integers using a data array data, a pointer array nextp, a start pointer and a free pointer.
  • Null pointers are stored as -1.

(a) The pointer array contains: index 0 → 4, index 2 → 0, index 4 → -1. The data array contains: 0 = 30, 2 = 12, 4 = 75. The start pointer is 2. State the order in which the integers are read from the list. [2]

(b) Write program code for a function find(target) that traverses the list and returns the index of the node holding target, or -1 if it is not in the list. [4]

(c) Write program code for a procedure insert_front(value) that inserts a value at the front of the list, taking a node from the free list, or outputs "List full" if no free node exists. [5]

Lab Task — Show mark scheme & model answer
Reveal the full mark scheme and model answers for parts (a), (b) and (c).
Hint:
  • (a) follow start = 2 through the pointers to null.
  • (b) current = start; while current != -1; compare and return index; follow nextp and return -1.
  • (c) check free empty + message; take free node; advance free; store value + point at old start; set start = new.

Key Points Summary

A linked list is a chain of nodes. Each node holds a data value and a pointer (next field) to the next node.
A start pointer gives the index of the first node; -1 means the list is empty.
The last node holds a null pointer (-1) — it points to nothing, marking the end of the list.
Items are added and removed by changing pointers, not by moving data. That is the main advantage over an array.
In Python we simulate the list with two arrays of the same length: data[] (the values) and nextp[] (the index of the next node).
A free list is a chain of unused nodes, ready to be taken when inserting. A free pointer marks its start.
setup() pre-links the free list: nextp[i] = i + 1, and nextp[MAX-1] = -1 (end of free list).
Traverse (find): set current = start; while current != -1, check data[current], then current = nextp[current]. The null pointer stops the loop — never a count.
find(target) returns the index of the node holding target, or -1 if it is not found.
insert_front(item): check free == -1 (full); new = free; free = nextp[free]; data[new] = item; nextp[new] = start; start = new.
Insert order: take node from free → advance free → store data → new node points to old start → start = new node. Never lose the free list.
delete(target): walk the list tracking current and previous; if found, point previous past it (or move start if it is first); then return the freed node to the free list.
After bypassing a deleted node: nextp[current] = free; free = current (return it to the front of the free list).
A linked list is a dynamic structure — it can grow and shrink at run time by adding/removing nodes from the free list.

19.7 Practice Tasks

Fifteen exam-style tasks. Click Hint for bullet-point guidance, then Help to reveal a worked Python solution.

1Practice Task — Declare the arrays and pointers [3 marks]
Declare a linked list with MAX = 8: the data array, the pointer array, start, and free. Add a setup() that pre-links the free list.
2Practice Task — is_empty() [2 marks]
Write a function is_empty() that returns True if the list has no nodes.
3Practice Task — Read order from a table [2 marks]
start = 1; nextp: 1→3, 3→0, 0→-1. data: 1="cat", 3="dog", 0="owl". State the order the data is read.
4Practice Task — find(target) [4 marks]
Write a function find(target) that returns the index of the node holding target, or -1.
5Practice Task — contains(target) [4 marks]
Write a function contains(target) that returns True if target is in the list, False otherwise.
6Practice Task — count_nodes() [4 marks]
Write a function count_nodes() that returns how many nodes are in the list.
7Practice Task — insert_front(item) [5 marks]
Write a procedure insert_front(item) that inserts at the front, taking a node from the free list, or prints "List full" if none is free.
8Practice Task — add_bookmark(url) [5 marks]
Write a procedure add_bookmark(url) that inserts a bookmark at the front, or prints "No space" if the list is full.
9Practice Task — delete(target) [6 marks]
Write a function delete(target) that removes the node holding target by re-linking pointers, returning it to the free list. Return True if deleted, False if not found.
10Practice Task — Trace a delete [3 marks]
List: start=2, data[2]=60/nextp[2]=1, data[1]=45/nextp[1]=0, data[0]=88/nextp[0]=-1, free=3. Trace delete(45). What are start, free and the new nextp[2] afterwards?
11Practice Task — delete the first node [3 marks]
List: start=2, data[2]=60/nextp[2]=1, data[1]=45/nextp[1]=0, data[0]=88/nextp[0]=-1. Trace delete(60) (the first node). What is start afterwards?
12Practice Task — print_list() [4 marks]
Write a procedure print_list() that traverses the list from start and prints each data value on its own line.
13Practice Task — to_python_list() [4 marks]
Write a function to_list() that traverses the linked list and returns a normal Python list of the data values in order.
14Practice Task — last_value() [5 marks]
Write a function last_value() that returns the data in the last node of the list, or None if the list is empty.
15Practice Task — Full exam-style: find + insert [9 marks]
(a) Write find(target) that returns the index of target or -1. [4] (b) Write insert_front(value) that takes a node from the free list, printing "List full" if none is free. [5]

Question Bank

Answer all questions, then press Submit Quiz to see your score.

0/12 answered

Question 1Multiple Choice

A linked list is best described as:

Question 2Multiple Choice

What does a null pointer (-1) represent in a linked list?

Question 3Multiple Choice

Which two arrays simulate a linked list in Python?

Question 4True / False

The start pointer stores the index of the first node in the list.

Question 5Multiple Choice

What is the free list?

Question 6Multiple Choice

In find(target), what is the correct loop condition?

Question 7Multiple Choice

In insert_front(item), what is the correct order of operations?

Question 8Multiple Choice

When deleting the first node (previous == -1), how is the node removed?

Question 9True / False

When deleting a node, you must move all the data after it to fill the gap.

Question 10Multiple Choice

After bypassing a deleted node, how do you return it to the free list?

Question 11Multiple Choice

A linked list is described as a "dynamic structure" because:

Question 12Multiple Choice

Given start = 2, nextp[2] = 1, nextp[1] = 0, nextp[0] = -1, and data[2] = 60, data[1] = 45, data[0] = 88, what is the read order?

Answer all 12 questions to enable submission.