Computer ScienceCore24 min read

Data Structures

Arrays, lists, stacks, queues, trees

This topic appears in:

01

The only question that matters

A data structure is not about storing things. Storage is easy. A data structure is about which operations you want to be fast, because you cannot have them all.

Every structure on this page holds exactly the same numbers. They differ only in what they make cheap and what they make expensive.

02

Array: one contiguous block

An array is a single unbroken run of memory. Because every element is the same size and they sit shoulder to shoulder, the computer can find element i with one multiplication: address = base + i × size. No searching. That is O(1) random access, and it is the array's superpower.

The price: inserting at the front means physically shifting every other element one slot right. That is O(n), and it gets worse the more data you have.

Switch to Linked list and press Get [2]. Notice the cost flips: the array reads instantly, the list has to walk. Then press Add front and watch the costs flip back.

03

Linked list: nodes holding hands

A linked list gives up contiguity. Each node stores its value plus a pointer to the next node, scattered anywhere in memory.

Inserting at the front is now trivial — make a new node, point it at the old head, done. O(1). But to reach element 2 you must start at the head and walk. There is no formula for where node 2 lives. O(n).

The trade in one sentence

Arrays are fast to read and slow to reshape. Linked lists are fast to reshape and slow to read. Choose based on which one your program does more often.

04

Stack and queue: arrays with a rule

A stack is LIFO — last in, first out. Only the top is reachable. Think of a stack of plates, or the browser back button, or how your program tracks nested function calls.

A queue is FIFO — first in, first out. You add at the back and remove from the front, exactly like a queue at a shop. Print jobs, task schedulers, and breadth-first search all run on queues.

Neither adds new capability. They add a restriction, and the restriction is the point: fewer legal operations means fewer ways for your code to be wrong.

05

Trees: when linear is not enough

A binary search tree keeps everything sorted by an invariant: everything smaller goes left, everything larger goes right. Searching then halves the remaining candidates at every step, giving O(log n) lookup — a million items in about twenty comparisons.

That is only true while the tree stays balanced. Insert already-sorted data into a naive BST and it degenerates into a linked list with O(n) lookup, which is why real systems use self-balancing variants like AVL or red-black trees.

Run In-order on this binary search tree. The visit sequence comes out perfectly sorted: 10, 20, 25, 30… That is not a coincidence, it is the BST invariant made visible.

06

Cost summary

StructureAccessSearchInsert frontInsert end
ArrayO(1)O(n)O(n)O(1) amortised
Linked listO(n)O(n)O(1)O(n) singly
StackO(1) top onlyO(n)O(1) push
QueueO(1) front onlyO(n)O(1) enqueue
Balanced BSTO(log n)O(log n)O(log n)O(log n)
Hash tableO(1) averageO(1) averageO(1) averageO(1) average
07

Choosing a structure for a real problem

Exam questions rarely ask what a stack is. They describe a situation and ask which structure suits it, which is a different skill: read the problem for the order in which items must come out, and for whether the size is known in advance.

The problem saysStructureBecause
undo the last actionstacklast in, first out
print jobs in the order sentqueuefirst in, first out
a fixed number of exam marksarraysize known, direct access by index
a list that grows unpredictablylinked listno fixed size, cheap insertion
look up a student by roll numberhash table or dictionarynear-instant lookup by key
a folder containing folderstreenaturally hierarchical
cities joined by roadsgraphmany-to-many connections

Stack or queue — read for the order

Both hold items waiting to be processed; they differ only in which one leaves first. A stack is last in, first out — undo, the back button, a call stack. A queue is first in, first out — print jobs, a ticket line, buffering. The question always contains the answer: "the most recent" means a stack, "in the order they arrived" means a queue.

08

Why the trade-off is unavoidable

There is no structure that is best at everything, and the reason is physical rather than a failure of imagination.

An array stores its items in one contiguous block, so the address of item 5000 can be calculated directly and reached instantly. That same contiguity is why inserting at the front requires shifting every later item along, and why the size must be fixed in advance.

A linked list stores each item wherever there is room, with a pointer to the next. Inserting is therefore cheap — change two pointers — and the list can grow indefinitely. But reaching item 5000 means following 5000 pointers, because there is no formula for where it lives.

Fast access and cheap insertion pull in opposite directions. Every structure in the chapter is a different point on that line.

Worked example

A program maintains a list of students that is searched constantly by position but almost never changed. Then a second program maintains a list that changes constantly but is only ever read from the start. Which structure suits each?

  1. First program: frequent access by position, rare modification → array.Direct indexing is instant, and the cost of insertion never arises because insertions are rare.
  2. Second program: frequent insertion and deletion, sequential reading only → linked list.Insertion is a pointer change, and reading from the start does not need indexing.
  3. Note that neither answer is about which structure is better.The question is which cost the program can afford to pay, and that depends entirely on what it does most often.

Array for the first, linked list for the second — decided by which operation is frequent.

Practice questions

6 questions · 25 marks · full working on every one

Try each one on paper first, then open the working. The marks are shown where they are actually awarded, because that is where they are actually lost.

Short questions

3 · 7 marks

Two marks each, in the style of the short-question section of the paper. Answer in two or three lines.

SQ1[2 marks]
State one advantage and one disadvantage of an array compared with a linked list.
Model answer

Advantage: any element can be reached directly from its index in constant time. Disadvantage: inserting at the front requires every later element to be shifted.

Examiner tip. One of each, and say why. A bare list of properties with no comparison rarely scores both.

SQ2[2 marks]
Explain the difference between a stack and a queue.
Model answer

A stack is last-in-first-out: items are added and removed at the same end. A queue is first-in-first-out: items are added at one end and removed from the other.

Examiner tip. LIFO and FIFO earn the marks, but only if you also say which end things enter and leave.

SQ3[3 marks]
A stack is implemented with an array and a pointer. Describe what happens to the pointer during a push and during a pop.
Model answer

On a push the pointer is incremented and the new item is written at that position. On a pop the item at the pointer is read and the pointer is decremented. The pointer must be checked against the array bounds first.

Examiner tip. The bounds check is the third mark — stack overflow on push, stack underflow on pop.

Long questions

2 · 13 marks

Theory and numerical together, as they appear in the long-question section.

LQ1[6 marks]
A program uses a queue to hold print jobs waiting for a printer.
  1. Explain why a queue is the appropriate structure for this task. [2]
  2. Describe how a circular queue avoids the problem of a linear queue in a fixed-size array. [3]
  3. State what must be checked before a job is added. [1]
Mark scheme
  1. Jobs must be printed in the order they were submitted[1]
  2. A queue removes items in the same order they were added, which is first-in-first-out[1]
  3. In a linear queue the front pointer moves forward and the space behind it is wasted[1]
  4. A circular queue wraps the rear pointer round to the start of the array[1]
  5. So the freed space is reused and the array does not appear full while space remains[1]
  6. That the queue is not full[1]

Examiner tip. Wrapping is usually done with modulo arithmetic: rear = (rear + 1) MOD size. Quoting that line makes the explanation concrete.

LQ2[7 marks]
A binary search tree is built by inserting the values 50, 30, 70, 20, 40, 60 in that order.
  1. Draw the resulting tree. [3]
  2. Write down the in-order traversal. [2]
  3. State what the in-order traversal of any binary search tree always produces, and give one use of that property. [2]
Mark scheme
  1. 50 at the root with 30 on its left and 70 on its right[1]
  2. 20 and 40 as the children of 30[1]
  3. 60 as the left child of 70[1]
  4. Visits left subtree, then node, then right subtree[1]
  5. 20, 30, 40, 50, 60, 70[1]
  6. The values in ascending order[1]
  7. It can therefore be used to sort the data, or to output it in order without re-sorting[1]

(b) 20, 30, 40, 50, 60, 70

Examiner tip. Insert each value by walking from the root, going left when smaller and right when larger. Building the tree in the wrong order is the only real difficulty here.

Exam questions

1 · 5 marks

Multi-part questions with a full mark scheme.

Q1[5 marks]
A linked list stores the names Ali, Bilal, Danish in alphabetical order. Each node holds a name and a pointer.
  1. Describe the steps needed to insert Chand in the correct position. [3]
  2. Explain why no data has to be moved, unlike in an array. [2]
Mark scheme
  1. Traverse from the head until the node after which Chand belongs is found, here Bilal[1]
  2. Create the new node and set its pointer to whatever Bilal was pointing at, that is Danish[1]
  3. Set Bilal's pointer to the new nodethis order matters or the rest of the list is lost[1]
  4. The nodes are not stored in consecutive memory locations[1]
  5. Order is held by the pointers, so changing two pointers is enough[1]

Examiner tip. Point the new node at the rest of the list BEFORE re-pointing the previous node. Do it the other way round and you have orphaned everything after the insertion.