AQA A-Level Computer Science: Programming and Data Structures
AQA A-Level Computer Science: Programming and Data Structures
AQA A-Level Computer Science demands far more than surface-level understanding. You must be able to design, implement, and reason about programs and data structures with real fluency. Unlike GCSE, where you could often get by with basic code tracing and short pseudo-code answers, A-Level expects you to write substantial programs, analyse algorithmic efficiency, and understand the theoretical foundations behind the tools you use.
This guide covers the programming and data structures content that runs through the entire qualification -- from the practical on-screen exam to the written theory paper and your coursework project.
How the Qualification is Structured
AQA A-Level Computer Science has three components, and programming knowledge appears across all of them:
Paper 1: On-screen Exam
- 2 hours 30 minutes, 100 marks (40% of A-Level)
- Taken on a computer with access to a programming environment
- Tests programming skills, computational thinking, and problem-solving through practical programming questions
- You will write, test, and debug actual code during this exam
Paper 2: Written Exam
- 2 hours 30 minutes, 100 marks (40% of A-Level)
- Tests theoretical knowledge across the full specification
- Data structures, algorithms, and Big-O notation appear here as written questions
- You may need to trace algorithms, draw diagrams, or explain how structures work on paper
Non-Exam Assessment (NEA)
- A programming project worth 75 marks (20% of A-Level)
- You choose a problem, design a solution, implement it, and evaluate your work
- This is where you demonstrate sustained, independent programming ability
Understanding this structure matters because it shapes how you revise. Paper 1 requires you to write working code under timed conditions. Paper 2 requires you to explain and analyse structures and algorithms in writing. The NEA requires you to apply everything in a real project. You cannot afford to neglect any one of these.
Object-Oriented Programming
Object-oriented programming (OOP) is a central topic at A-Level. AQA expects you to understand OOP both practically -- writing classes and using objects in code -- and theoretically -- explaining the principles and their benefits.
Classes and Objects
A class is a blueprint that defines the attributes (data) and methods (behaviour) that objects of that type will have. An object is a specific instance of a class. For example, a Dog class might define attributes like name and breed, and methods like bark(). Each individual dog you create from that class is an object.
You must be comfortable creating classes, instantiating objects, and calling methods on those objects in your chosen programming language.
Encapsulation
Encapsulation means bundling data and the methods that operate on that data within a single unit (the class), and restricting direct access to the internal state. Attributes are typically made private, and access is provided through public getter and setter methods. This protects the integrity of the data -- external code cannot put an object into an invalid state if it must go through controlled methods.
On Paper 2, you may be asked to explain why encapsulation is beneficial. Focus on data protection, reduced coupling between parts of a program, and easier maintenance.
Inheritance
Inheritance allows a new class (the subclass or child class) to take on the attributes and methods of an existing class (the superclass or parent class). The subclass can then add new attributes or methods, or override existing ones. This promotes code reuse and creates a logical hierarchy.
For example, a Vehicle superclass might have attributes like speed and fuelLevel, with subclasses Car and Lorry adding their own specific attributes.
Polymorphism
Polymorphism means "many forms." In practice, it means that objects of different classes can respond to the same method call in different ways. If both Car and Lorry inherit from Vehicle and each overrides a calculateTax() method, you can call calculateTax() on any vehicle without knowing its specific type -- the correct version runs automatically.
This is closely linked to method overriding (a subclass provides its own implementation of a method defined in the superclass) and, in some languages, method overloading (multiple methods with the same name but different parameters).
Aggregation and Composition
These describe relationships between objects:
- Aggregation is a "has-a" relationship where the contained object can exist independently. A
DepartmenthasEmployeeobjects, but employees can exist without the department. - Composition is a stronger "has-a" relationship where the contained object cannot exist without the container. A
HousehasRoomobjects -- if the house is destroyed, the rooms cease to exist.
AQA expects you to distinguish between these and to draw or interpret class diagrams showing these relationships.
Programming Paradigms
AQA requires you to understand different approaches to programming, not just OOP.
Procedural Programming
Procedural programming structures code as a sequence of instructions, organised into procedures (subroutines) that operate on data. It uses constructs like sequence, selection, and iteration. This is likely how you first learned to program. It works well for smaller programs but can become difficult to manage as programs grow.
Object-Oriented Programming
As covered above, OOP organises code around objects that combine data and behaviour. It is well suited to large, complex systems because it promotes modularity, reuse, and abstraction.
Functional Programming
Functional programming treats computation as the evaluation of mathematical functions. It avoids changing state and mutable data, instead building programs from pure functions that always return the same output for the same input. Key concepts include first-class functions, higher-order functions, map, filter, fold, and function application. AQA covers functional programming as a distinct topic -- for a detailed breakdown, see our dedicated functional programming revision post.
Understanding the strengths and weaknesses of each paradigm, and when each is appropriate, is important for Paper 2 questions that ask you to compare approaches.
Data Structures
Data structures are how you organise and store data so that it can be used efficiently. AQA covers a wide range, and you need to understand both the abstract concept and the practical implementation of each.
Arrays
An array is a fixed-size, ordered collection of elements, all of the same data type. Elements are accessed by index (position).
- 1D arrays store a single list of values -- for example, a list of test scores.
- 2D arrays store data in rows and columns -- for example, a grid or a table. You access elements using two indices: one for the row and one for the column.
Arrays are efficient for random access (you can jump directly to any element by index) but inflexible in size -- you cannot easily add or remove elements.
Records
A record groups related data of different types under one name. For example, a student record might contain a string for name, an integer for age, and a float for average mark. In Python, you might implement this with a class or a dictionary; in other languages, records are a built-in construct.
Lists and Tuples
- Lists are ordered, mutable collections that can grow and shrink dynamically. In Python, lists are built in and extremely versatile.
- Tuples are ordered, immutable collections. Once created, their elements cannot be changed. They are useful when you want to guarantee that data will not be modified.
Understanding the difference between mutable and immutable structures is important for both Paper 1 (choosing the right structure in code) and Paper 2 (explaining trade-offs).
Stacks
A stack is a last-in, first-out (LIFO) structure. You can only add (push) and remove (pop) items from the top. Think of a stack of plates -- you always take the top plate.
Key operations:
- Push -- add an item to the top
- Pop -- remove and return the item from the top
- Peek -- view the top item without removing it
- isEmpty -- check whether the stack is empty
Stacks are used in function call management (the call stack), expression evaluation, undo mechanisms, and backtracking algorithms.
Queues
A queue is a first-in, first-out (FIFO) structure. Items are added at the rear (enqueue) and removed from the front (dequeue). Think of a queue of people waiting in line.
Key operations:
- Enqueue -- add an item to the rear
- Dequeue -- remove and return the item from the front
- isEmpty -- check whether the queue is empty
AQA may also expect you to know about priority queues (items are dequeued based on priority rather than order of arrival) and circular queues (the queue wraps around to use space efficiently in a fixed-size array).
Implementing Stacks and Queues
You need to know two approaches:
Array-based implementation: Use a fixed-size array with a pointer (or index variable) tracking the top of the stack or the front and rear of the queue. This is simple and memory-efficient but limited by the array size. For a circular queue, you use modular arithmetic to wrap the rear and front pointers around.
Pointer-based (linked list) implementation: Each element is a node containing the data and a pointer to the next node. This allows dynamic sizing -- the structure grows and shrinks as needed -- but uses more memory per element due to the pointer overhead.
On Paper 1, you may be asked to implement these in code. On Paper 2, you may be asked to trace operations on a diagram, explain the advantages and disadvantages of each approach, or identify when each is appropriate.
Linked Lists
A linked list is a dynamic data structure where each element (node) contains data and a pointer to the next node. Unlike arrays, linked lists do not store elements in contiguous memory, so inserting or deleting elements is efficient (you just update pointers) but random access is slow (you must traverse from the start).
You should understand:
- How to traverse a linked list
- How to insert and delete nodes at the beginning, end, or middle
- The difference between singly linked lists (each node points to the next) and doubly linked lists (each node points to both the next and previous)
Trees
Binary trees are hierarchical structures where each node has at most two children (left and right). A binary search tree (BST) is a binary tree with an ordering property: for any node, all values in its left subtree are smaller, and all values in its right subtree are larger. This makes searching efficient.
Key operations on a BST:
- Searching -- compare the target with the current node and go left or right accordingly
- Inserting -- find the correct position using the search process and add the new node
- Traversals -- in-order (left, root, right), pre-order (root, left, right), post-order (left, right, root)
In-order traversal of a BST returns the elements in sorted order -- this is a common exam question.
Hash Tables
A hash table stores key-value pairs. A hash function takes the key and computes an index in an array where the value is stored. This gives O(1) average-case access time.
The main challenge is collisions -- when two keys hash to the same index. You should know collision resolution strategies:
- Open addressing (linear probing) -- if the slot is taken, check the next slot along
- Chaining -- each slot holds a linked list of all entries that hash to that index
You should be able to explain the trade-offs: hash tables are fast on average but performance degrades with many collisions, and they do not maintain any ordering of the data.
Graphs
A graph is a set of vertices (nodes) connected by edges. Graphs can be:
- Directed or undirected (edges have a direction or not)
- Weighted or unweighted (edges have associated values or not)
Graphs can be represented as:
- Adjacency matrices -- a 2D array where entry [i][j] indicates whether an edge exists between vertices i and j (good for dense graphs, O(1) edge lookup, but uses more memory)
- Adjacency lists -- each vertex has a list of its neighbours (good for sparse graphs, uses less memory, but edge lookup is slower)
Graphs model real-world networks such as social connections, transport routes, and computer networks. Graph traversal algorithms (breadth-first search and depth-first search) are covered in the algorithms section of the specification and may connect to data structure questions.
Recursion
Recursion is when a function calls itself. Every recursive function must have:
- A base case -- a condition that stops the recursion
- A recursive case -- where the function calls itself with a modified argument, moving towards the base case
How Recursion Works -- Stack Frames
Each recursive call creates a new stack frame on the call stack, holding the function's local variables and return address. When the base case is reached, the frames unwind -- each call returns its result to the one that called it.
This is why infinite recursion (missing or unreachable base case) causes a stack overflow -- the call stack runs out of space.
Recursion vs Iteration
Any recursive solution can be rewritten iteratively, and vice versa. The choice involves trade-offs:
- Recursion produces cleaner, more elegant code for problems that are naturally recursive (tree traversals, divide-and-conquer algorithms). However, it uses more memory (due to stack frames) and can be slower due to function call overhead.
- Iteration is generally more memory-efficient and can be faster, but the code may be less intuitive for inherently recursive problems.
On Paper 2, you may be asked to trace a recursive function, identify the base case and recursive case, explain how the call stack operates, or compare recursive and iterative approaches.
Big-O Notation and Algorithm Efficiency
Big-O notation describes how the time (or space) requirements of an algorithm grow relative to the input size. It focuses on the worst-case or general growth rate, ignoring constants and lower-order terms.
Common Complexities
-
O(1) -- Constant time. The operation takes the same time regardless of input size. Example: accessing an array element by index, or looking up a value in a hash table (average case).
-
O(log n) -- Logarithmic time. The input is halved at each step. Example: binary search on a sorted array.
-
O(n) -- Linear time. Time grows proportionally with input size. Example: linear search, traversing a linked list.
-
O(n log n) -- Linearithmic time. Typical of efficient sorting algorithms. Example: merge sort, quick sort (average case).
-
O(n^2) -- Quadratic time. Time grows with the square of input size. Example: bubble sort, insertion sort, nested loops over the same data.
Why This Matters
Understanding Big-O allows you to:
- Choose the most efficient algorithm or data structure for a given problem
- Predict how performance will change as data sets grow
- Justify your choices in the NEA and in exam answers
On Paper 2, you may be asked to state the time complexity of a given algorithm, compare two algorithms' efficiencies, or explain why one approach is preferred over another for large data sets.
Testing
Testing is an essential part of software development, and AQA expects you to understand it both for Paper 1 (where you must test your own code) and Paper 2 (where you may answer questions about testing strategies).
Types of Testing
- Unit testing -- testing individual modules, functions, or classes in isolation
- Integration testing -- testing how modules work together
- System testing -- testing the complete system against the requirements
- Acceptance testing -- testing with end users to confirm the system meets their needs
Test Data
You must choose test data systematically:
- Normal (typical) data -- valid inputs within the expected range. Tests that the program works under standard conditions.
- Boundary (edge) data -- values at the limits of acceptable ranges. If a field accepts values 1--100, test with 1, 100, and values just outside (0 and 101).
- Erroneous (invalid) data -- inputs that should be rejected. Tests that the program handles bad input gracefully without crashing.
Debugging Strategies
- Trace tables -- manually tracking variable values through each line of code
- Breakpoints -- pausing execution at a specific line to inspect the program state
- Stepping -- executing code one line at a time to follow the flow of execution
- Watch variables -- monitoring specific variables as the program runs
- Print statements -- inserting temporary output statements to check values at key points
On Paper 1, you will be writing and running code on a computer, so effective debugging is a practical necessity. You will not always get your code right on the first attempt, and candidates who can systematically find and fix errors will score significantly higher.
How These Topics Appear in the Exams
Paper 1 -- Practical Programming
Paper 1 is sat on a computer. You will open a programming environment and write real code to solve problems. Questions may ask you to:
- Write classes with specified attributes and methods, using inheritance and polymorphism
- Implement or use data structures (stacks, queues, linked lists, trees, hash tables)
- Write recursive functions
- Read from and write to files
- Test and debug provided or partially complete programs
The key to Paper 1 is practice. You must be fluent enough in your programming language that you can write correct, working code under time pressure. Knowing the theory is not sufficient -- you need to have implemented these structures and patterns many times before the exam.
Paper 2 -- Written Theory
Paper 2 tests your ability to explain, analyse, and reason about programming concepts on paper. You may be asked to:
- Draw and annotate diagrams of data structures (linked lists, trees, hash tables)
- Trace algorithms step by step, showing how a data structure changes
- Explain OOP principles and justify their use in a given scenario
- Compare the efficiency of algorithms using Big-O notation
- Describe the advantages and disadvantages of different data structures for a given problem
- Explain recursion, identify base cases, and trace recursive calls
Precision matters on Paper 2. Use correct technical terminology. When comparing data structures, be specific about time and space trade-offs rather than giving vague answers.
Exam Strategy Tips
-
For Paper 1: Build a library of practiced implementations before the exam. You should have written stacks, queues, linked lists, binary search trees, and hash tables from scratch multiple times. In the exam, read each question carefully -- the exact requirements matter.
-
For Paper 2: Practice drawing data structure diagrams under timed conditions. When asked to trace an algorithm, set out your working clearly -- even if your final answer is wrong, you can earn method marks for correct intermediate steps.
-
For the NEA: Choose a project that genuinely requires the data structures and OOP concepts on the specification. Using a linked list or binary search tree where appropriate will demonstrate higher-level skills and strengthen your mark for technical complexity.
-
Know both representations: For data structures like graphs, make sure you can work with both adjacency matrices and adjacency lists. For stacks and queues, make sure you can implement both array-based and pointer-based versions.
-
Link theory to practice: When explaining Big-O on Paper 2, use concrete examples. Saying "binary search is O(log n) because it halves the search space at each step" is far stronger than simply stating the complexity.
Prepare with LearningBro
Revising programming and data structures requires active practice, not passive reading. Our courses provide targeted questions that test your understanding of every topic covered in this guide:
- AQA A-Level Computer Science: Programming and OOP -- covering classes, inheritance, polymorphism, encapsulation, and practical programming skills
- AQA A-Level Computer Science: Data Structures -- covering stacks, queues, linked lists, trees, hash tables, graphs, recursion, and algorithm efficiency
Work through these alongside your own coding practice to build the fluency you need for Paper 1 and the depth of understanding you need for Paper 2.