Abstract data types/data structures — AQA A-Level Computer Science
An Abstract Data Type (ADT) is a logical description of how data is viewed and manipulated, defined by its behaviour and operations rather than its concrete implementation. In AQA A-Level Computer Science, mastering ADTs such as stacks, queues, trees, graphs, and hash tables requires understanding their static versus dynamic implementations and algorithmic efficiencies.
Abstract data types/data structures explained
A stack is an abstract data type that stores items in a last in, first out (LIFO) order.
Read the full explanation
Items are added to the top with a push operation and removed from the top with a pop operation, so the most recently added item is always the first to be removed. Stacks are often implemented as an array with a pointer to the top element, or as a linked list where the head node is the top. A typical use is tracking return addresses for subroutine calls, where the most recent call must return first. Because access is restricted to the top, a stack does not allow direct access to items deeper in the structure. Understanding the operations and their order of effect is the key to answering questions about stacks correctly.
What to demonstrate
- Identifies the stack as LIFO, meaning the last item pushed is the first item popped.
- Describes push as adding an item to the top and pop as removing the item from the top.
- Recognises that only the top element is directly accessible at any time.
Show all 4 objectives
- Links the stack to a practical use such as subroutine return addresses or undo functionality.
Which command word is this?
Set out the mathematical or logical reasons for how an ADT operates or why a specific implementation is chosen, connecting causes to computational consequences.
Abstract data types/data structures exam tips
Topic Overview
Abstract Data Types (ADTs) provide high-level models of data storage that encapsulate data representation behind well-defined operational interfaces. In AQA A-Level Computer Science, this topic explores both the conceptual mechanics and the practical implementations of stacks, queues, linked lists, trees, graphs, hash tables, and dictionaries.
Understanding ADTs bridges the gap between software design and algorithmic efficiency. Selecting the correct data structure directly governs the time and space complexity of computational solutions, forming a foundational component of Paper 1 and Paper 2 assessment objectives.
Key Concepts
- →Abstraction vs Implementation: An ADT describes what operations can be performed (e.g., push, pop, peek), whereas a data structure represents how those operations are physically stored in memory.
- →Static vs Dynamic Data Structures: Static structures have fixed memory allocations determined at compile time (e.g., fixed-size arrays), while dynamic structures allocate memory from the heap at runtime using pointers.
- →Linear vs Non-Linear Structures: Stacks, queues, and linked lists store elements sequentially, while trees and graphs represent non-linear hierarchical or interconnected network relationships.
- →Collision Resolution in Hash Tables: Techniques such as open addressing (linear probing) and closed addressing (chaining with linked lists) resolve scenarios where two distinct keys hash to the same index.
Marking Points
- Identifies the stack as LIFO, meaning the last item pushed is the first item popped.
- Describes push as adding an item to the top and pop as removing the item from the top.
- Recognises that only the top element is directly accessible at any time.
- Links the stack to a practical use such as subroutine return addresses or undo functionality.
Examiner Tips
- 💡Trace a short sequence of push and pop operations step by step on paper to check the final contents.
- 💡Remember that the most recently pushed item is always the next one popped.
- 💡When an MCQ asks about removal order, check whether the answer option reflects last in, first out.
- 💡When drawing or tracing pointer operations for linked lists and trees, explicitly label pointer variables (e.g. 'Head', 'Prev', 'Curr') and denote null pointers clearly using ground symbols or the value 'null'.
- 💡Always state time complexities using Big-O notation when comparing operations across structures (e.g., hash table retrieval is O(1) average case, whereas unindexed linked list search is O(n)).
- 💡In pseudocode questions, remember to implement defensive programming checks: verify 'isFull()' before pushing/enqueueing and 'isEmpty()' before popping/dequeueing.
Common Mistakes
- Treats a stack as FIFO, which is the behaviour of a queue; correct by remembering that a stack reverses the order of arrival.
- Assumes items can be removed from the bottom or middle; correct by restricting removal to the top only.
- Confuses push and pop, or reverses their effects; correct by linking push to adding and pop to removing from the top.
- Assuming dynamic data structures are always superior to static data structures. While dynamic structures avoid overflow and conserve unused memory, they incur memory overhead for pointer storage and lack direct random index access.
- Believing a circular queue moves items in memory during dequeue operations. Circular queues use modulo arithmetic to advance pointer indices; the existing data elements are not physically shifted.
- Confusing graph traversals with tree traversals. Graphs may contain cycles and disconnected components, requiring a 'visited' set or boolean flags to prevent infinite loops during BFS or DFS traversals.
Revision Plan
- 1Day 1-3: Master linear ADTs. Code and trace stacks, linear queues, circular queues, and priority queues using static arrays and dynamic linked lists.
- 2Day 4-6: Study non-linear structures. Practice manual insertion, deletion, and tree traversals (pre-order, in-order, post-order) for binary search trees.
- 3Day 7-9: Explore graphs and hash tables. Implement adjacency matrices vs adjacency lists, hash functions, and collision resolution strategies.
- 4Day 10-12: Solve past AQA exam questions focusing on 6-mark comparative essays, pointer-trace diagrams, and pseudocode algorithms.
Exam Question Types
- 📋Trace and diagram questions: Filling tables or drawing diagrams to trace pointers, stack frames, or queue indices across sequential operations.
- 📋Algorithm implementation: Writing or completing pseudocode for core operations like tree insertions, linked list deletions, or hash table lookups.
- 📋Comparative analysis: Evaluating trade-offs between static vs dynamic structures or adjacency matrices vs adjacency lists for specific application contexts.
Command Word Expectations (AQA)
Set out the mathematical or logical reasons for how an ADT operates or why a specific implementation is chosen, connecting causes to computational consequences.
Identify both similarities and differences between two data structures (e.g. static vs dynamic, array vs linked list), referring to memory usage, runtime complexity, and ease of implementation.
Produce syntactically consistent pseudocode or structured English detailing exact steps, variable initialization, conditionals, pointer manipulations, and boundary checks.
How Students Lose Marks (Examiner Pitfalls)
Step-by-Step Worked Solutions
Question: A circular queue of capacity 5 is implemented using a 0-indexed static array named 'queueArray', with integer pointers 'front' and 'rear', and an integer 'size'. Initially, the queue is empty: front = 0, rear = -1, size = 0. Show the internal state of the array and pointers after the following sequence of operations: enqueue('A'), enqueue('B'), enqueue('C'), dequeue(), enqueue('D'), enqueue('E'), dequeue(), enqueue('F').
- 1.Step 1: Understand formulas for circular queues: rear = (rear + 1) mod capacity upon enqueue; front = (front + 1) mod capacity upon dequeue; size tracks current item count.
- 2.Step 2: Trace operations: enqueue('A') sets queueArray[0]='A', rear=0, size=1. enqueue('B') sets queueArray[1]='B', rear=1, size=2. enqueue('C') sets queueArray[2]='C', rear=2, size=3.
- 3.Step 3: Process dequeue(): removes 'A', front becomes (0+1) mod 5 = 1, size=2.
- 4.Step 4: Process enqueue('D'): rear becomes (2+1) mod 5 = 3, queueArray[3]='D', size=3. Process enqueue('E'): rear becomes (3+1) mod 5 = 4, queueArray[4]='E', size=4.
- 5.Step 5: Process dequeue(): removes 'B', front becomes (1+1) mod 5 = 2, size=3.
- 6.Step 6: Process enqueue('F'): rear wraps around: (4+1) mod 5 = 0, queueArray[0]='F', size=4.
- 7.Step 7: Final array state: index 0 = 'F', index 1 = empty/stale ('B'), index 2 = 'C', index 3 = 'D', index 4 = 'E'.
Question: Given the following values to be inserted into an initially empty binary search tree (BST) in order: [47, 23, 65, 12, 38, 54, 78, 31]. Describe the construction of the tree, determine the height of the resulting tree (counting root as height 0), and list the nodes in post-order traversal.
- 1.Step 1: Insert 47 as root.
- 2.Step 2: 23 < 47 (left child of 47). 65 > 47 (right child of 47).
- 3.Step 3: 12 < 47 and 12 < 23 (left child of 23). 38 < 47 and 38 > 23 (right child of 23).
- 4.Step 4: 54 > 47 and 54 < 65 (left child of 65). 78 > 47 and 78 > 65 (right child of 65).
- 5.Step 5: 31 < 47, 31 > 23, 31 < 38 (left child of 38).
- 6.Step 6: Identify levels: Level 0: 47; Level 1: 23, 65; Level 2: 12, 38, 54, 78; Level 3: 31. Height is 3.
- 7.Step 7: Post-order traversal rule is Left-Right-Root recursively: Left subtree of root (rooted at 23): Left is 12; Right subtree is 38 (which has left 31, right null, root 38 -> 31, 38); Root is 23. Yields: 12, 31, 38, 23. Right subtree of root (rooted at 65): Left is 54; Right is 78; Root is 65. Yields: 54, 78, 65. Root is 47.