KS5H446 1.4.2 38 min read 10 question quiz 24 exam marks

Data Structures

Arrays, records, lists, tuples, stacks, queues, linked lists, graphs, trees and hash tables, with the operations and when to choose each.

Linear structures

Arrays, records, lists and tuples

StructureProperties
ArrayFixed size, same data type, contiguous memory, direct access by index in constant time
RecordFixed set of named fields of possibly different types, a row in a file
ListOrdered, may hold mixed types, dynamic size, may not be contiguous
TupleOrdered and immutable once created

An array's index calculation is base address + index x element size, which is why access is constant time and why elements must all be the same size.

Stacks

Last in, first out. Operations: push, pop, peek, isEmpty, isFull.

OCR reference language
procedure push(item)
    if top == maxSize - 1 then
        return "Stack overflow"
    endif
    top = top + 1
    stack[top] = item
endprocedure

function pop()
    if top == -1 then
        return "Stack underflow"
    endif
    item = stack[top]
    top = top - 1
    return item
endfunction

Uses: the call stack holding return addresses and local variables, undo functionality, evaluating reverse Polish notation, backtracking, and depth first search.

Queues

First in, first out. Operations: enqueue, dequeue, isEmpty, isFull.

A linear queue wastes space as the front pointer advances. A circular queue solves this by wrapping the pointers using modulo arithmetic:

rear = (rear + 1) MOD maxSize

A priority queue dequeues the highest priority item rather than the oldest.

Uses: print spoolers, keyboard buffers, process scheduling, breadth first search.

Linked lists

Each node holds data and a pointer to the next node. A separate pointer marks the start, and a null pointer marks the end.

ArrayLinked list
MemoryContiguousAnywhere, connected by pointers
SizeFixed at creationGrows and shrinks dynamically
AccessDirect by index, constant timeMust traverse from the start, linear time
Insertion in the middleRequires shifting every later elementChange two pointers
OverheadNoneA pointer stored per node

Insertion is the key difference. Inserting into the middle of an array of a million elements means moving up to a million items. In a linked list it means changing two pointers.

An array compared with a linked listTwo data structures compared. An array holds Ada, Bob, Cai, Dee and Eve in one continuous block of memory at addresses 400, 404, 408, 412 and 416, indexed 0 to 4. Because the items are evenly spaced the computer can jump straight to any index by calculating start address plus index times item size, but inserting an item in the middle means shifting every item after it, and the array cannot grow beyond its declared size. A linked list holds the same names in nodes scattered anywhere in memory. Ada sits at address 512 and its next pointer holds 730, where Bob sits. Bob's pointer holds 604 for Cai. Cai's pointer holds 918 for Dee. Dee's pointer holds null, marking the end. Reaching the fourth item means following three pointers from the head, but inserting in the middle only changes two pointers and the list can grow as long as there is free memory.ARRAYone block of memory, fixed sizeAdaindex 0address 400Bobindex 1address 404Caiindex 2address 408Deeindex 3address 412Eveindex 4address 416To reach index 3 the computer works out 400 + 3 x 4 and jumps straight there.Inserting in the middle means shifting every item after it along by one.LINKED LISTscattered nodes, each holding a pointer to the nextAdaat 512next730Bobat 730next604Caiat 604next918Deeat 918nextnullTo reach the fourth item you must start at the head and follow three pointers.Inserting in the middle changes two pointers, and the list can grow at any time.
Arrays win on reading a known position. Linked lists win on inserting and deleting, and on not needing to know the size in advance.
A stack compared with a queueTwo abstract data structures compared. A stack holds A at the bottom, then B, then C, with D on top. Both operations act on the top: push adds a new item onto the top and pop removes the top item, so the last item pushed is the first one popped. That is why a stack is called last in, first out, and why it suits undo history and the call stack. A queue holds A at the front, then B, C and D at the back. Enqueue adds a new item at the back and dequeue removes the item at the front, so items leave in the order they arrived. That is why a queue is called first in, first out, and why it suits print jobs and keyboard buffers.STACKlast in, first outDCBApushpopboth happen at the same end, the topQUEUEfirst in, first outABCDfrontbackdequeueenqueue at the backitems leave in the order they arrived
A stack needs one pointer, to the top. A queue needs two, to the front and to the back.
A stack of plates and a queue at a tillTwo linear data structures, drawn as the two physical things they are named after. A stack is a pile of plates: items are pushed onto the top and popped off the top, so the last item in is the first one out, which is called LIFO. Pushing first, then second, then third gives a pile with third on top, and popping returns third. Only the top item can be reached, and a pointer records where the top is. Stacks are what a computer uses to remember where to return to after a subroutine call, and to undo. A queue is a line of people at a till: new items join the back and items leave from the front, so the first item in is the first one out, which is called FIFO. Queues are used where things must be handled in the order they arrived, such as print jobs and keyboard input.Stack: last in, first outQueue: first in, first out1st2nd3rdpushpoponly the top plate can be reachedthe last one on is the first one off£till1234enqueuejoins the backdequeueserved from the frontBACKFRONT12345
  1. A stack is a pile. New items go on the top.
  2. Push another one and it goes on top again.
  3. Pop takes the top one off, so the last in is the first out.
  4. A queue is a line. New items join the back.
  5. Dequeue takes from the front, so the first in is the first out.
LIFO and FIFO are not jargon to memorise. A stack of plates and a queue at a shop behave exactly like this.
Evaluating the postfix expression 3 4 + 2 * with a stack, one token at a timeThe infix expression, 3 plus 4 in brackets, times 2, is converted by the shunting yard algorithm into the postfix expression 3 4 + 2 *, which needs no brackets because the order of the tokens is the meaning. It is evaluated with a stack, one token at a time. The token 3 is pushed, so the stack holds 3. The token 4 is pushed, so the stack holds 3 and 4. The token plus pops 4 and 3 and pushes their sum, 7. The token 2 is pushed, so the stack holds 7 and 2. The token times pops 2 and 7 and pushes 14. The answer is the one value left on the stack, 14.1infix(3 + 4) * 2shunting yardpostfix3 4 + 2 *no brackets needed:the order is the meaningEvaluate it with a stack, one token at a time23token 13push 34token 234push 4+token 37pop 4 and 3, push 3+ 4 = 72token 472push 2*token 514pop 2 and 7, push 7× 2 = 14The answer is the one value left on the stack: 14.3
  1. Infix has the operator between the numbers and needs brackets. Postfix puts the operator after them.
  2. Numbers are pushed on the stack. An operator pops two values, applies itself and pushes the result.
  3. When the tokens run out, the single value left on the stack is the answer.
Postfix is easy for a computer because it needs no brackets and no rules about precedence: just a stack.

Trees, graphs and hash tables

Graphs

A set of vertices connected by edges. Edges may be directed or undirected, and weighted or unweighted.

Adjacency matrix. A two dimensional array where entry (i, j) records an edge from i to j.

  • Constant time to check whether an edge exists
  • Uses n2 space regardless of how few edges there are, so it wastes memory on sparse graphs
  • Better for dense graphs

Adjacency list. Each vertex stores a list of its neighbours.

  • Space proportional to the number of edges, so far more efficient for sparse graphs
  • Checking a specific edge requires searching a list
  • Better for sparse graphs

Uses: road and rail networks, social networks, the web, dependency graphs, state machines.

Trees

A connected acyclic graph with a root, parent and child nodes, and leaves with no children.

A binary search tree keeps values ordered: everything in the left subtree is smaller than the node, everything in the right subtree is larger.

  • Search, insert and delete average O(log n)
  • Degenerates to O(n) if items are inserted in sorted order, producing a linked list
  • Self balancing trees avoid this

Traversals

OCR reference language
procedure preOrder(node)      // node, left, right - copying a tree
procedure inOrder(node)       // left, node, right - visits in sorted order
procedure postOrder(node)     // left, right, node - deleting, or postfix expressions

In order traversal of a binary search tree outputs the values in ascending order. This is examined frequently.

Hash tables

A hash function maps a key to an index in an array, giving average constant time insertion and lookup.

A collision occurs when two keys hash to the same index.

  • Separate chaining. Each slot holds a list of all items hashing there. Simple, and degrades gracefully.
  • Open addressing or linear probing. On collision, try the next free slot. No extra structures, but causes clustering which degrades performance.

The load factor is the number of items divided by the number of slots. As it rises, collisions become frequent and performance falls, so the table is rehashed into a larger array when it passes a threshold, typically around 0.7.

Choosing a structure

Frequent lookup by key means a hash table. Ordered data needing range queries means a binary search tree. Frequent insertion in the middle means a linked list. Fixed size with index access means an array.

A binary search tree and its three traversal ordersA binary search tree with root 8. The root's left child is 3 and its right child is 10. Node 3 has children 1 and 6. Node 6 has children 4 and 7. Node 10 has a right child 14, and 14 has a left child 13. Every value in a left subtree is smaller than its parent and every value in a right subtree is larger. Traversing pre-order, which visits root then left then right, gives 8, 3, 1, 6, 4, 7, 10, 14, 13. Traversing in-order, which visits left then root then right, gives 1, 3, 4, 6, 7, 8, 10, 13, 14, which is ascending order. Traversing post-order, which visits left then right then root, gives 1, 4, 7, 6, 3, 13, 14, 10, 8.831016144713A binary search treesmaller values go left, larger values go rightPre-orderroot, left, right8 3 1 6 4 7 10 14 13In-orderleft, root, right1 3 4 6 7 8 10 13 14Post-orderleft, right, root1 4 7 6 3 13 14 10 8in-order always comes out in ascending order
The name of each traversal tells you when the root is visited: pre means before the subtrees, in means between them, post means after.
A binary search treeA binary search tree holding the values 50, 30, 70, 20, 37, 60 and 90. Every node has at most two children, the node at the top is the root, and the nodes with no children at the bottom are the leaves. What makes it a search tree rather than just a binary tree is the rule about where things go: anything smaller than a node is placed in its left subtree and anything larger in its right subtree. Searching is then a matter of comparing and moving. To find 37, start at the root, 50. 37 is smaller, so go left to 30. 37 is larger than 30, so go right, and there it is. Three comparisons for seven items, because each comparison throws away half of what is left, in the same way a binary search does on a sorted list. That is why a balanced tree of a million items needs about twenty comparisons rather than a million.A binary search tree50307020376090rootfind 3737 < 50: go left37 > 30: go rightfound!leaves: no childrenThe rule302037smallerlargerleft < parent < rightWhy it is fast7 items to search20303750607090after 1 comparison: 3 left203037after 2 comparisons: 1 left37a million items needsonly about 20 comparisons12345
  1. A binary tree: every node has at most two children.
  2. In a binary search tree, smaller goes left and larger goes right.
  3. Searching for 37: start at the root and compare.
  4. 37 is less than 50, so go left. More than 30, so go right. Found.
  5. Three comparisons for seven items. That is why trees are fast.
Every comparison halves what is left. A tree is binary search, built into the shape of the data.
Keys hashed into the buckets of a hash table, with a collisionA hash table stores each key in a bucket chosen by a hash function. Here the hash function adds up the character codes of the key, divides by 8 and keeps the remainder. For Ada that is 65 plus 100 plus 97, which is 262, and 262 mod 8 is 6, so Ada goes in bucket 6. Bob goes in bucket 3, Eve in bucket 0, and Zed also gives 3. Bob and Zed hash to the same bucket, which is a collision, and here it is handled by chaining: both are kept in a list in bucket 3.Keys1Hash function2Array of 8 buckets3add the character codes,then divide by 8 andkeep the remainderAda: 65+100+97     = 262262 mod 8 = 6AdaBobZedEve01234567AdaBobZedEveBob and Zed both give 3.That is a collision, so theyare chained in bucket 3.
  1. Four keys to store: Ada, Bob, Zed and Eve.
  2. The hash function turns each key into a bucket number, for Ada 65 + 100 + 97 = 262, and 262 mod 8 = 6.
  3. Each key is stored in its bucket. Bob and Zed both give 3, which is a collision, so they are chained in the same bucket.
Lookup is fast because the hash goes straight to the bucket, instead of searching. A good hash function spreads keys evenly.

Key terms you must be able to define

Array
A fixed size collection of items of the same type in contiguous memory, accessed by index.
Record
A structure holding a fixed set of named fields, which may be of different types.
Tuple
An ordered collection that cannot be changed after creation.
Stack
A last in first out structure supporting push and pop.
Queue
A first in first out structure supporting enqueue and dequeue.
Circular queue
A queue whose pointers wrap around using modulo arithmetic to avoid wasting space.
Linked list
A structure of nodes each holding data and a pointer to the next node.
Graph
A set of vertices connected by edges, which may be directed or weighted.
Adjacency matrix
A two dimensional array recording which vertices are connected.
Adjacency list
A representation where each vertex stores a list of its neighbours.
Binary search tree
A tree where the left subtree holds smaller values and the right subtree larger ones.
In order traversal
Visiting left subtree, node, then right subtree, which outputs a BST in ascending order.
Hash table
A structure using a hash function to map keys to array indexes for constant time access.
Collision
Two keys hashing to the same index in a hash table.
Load factor
The ratio of stored items to available slots in a hash table.

Flashcards

Say the definition out loud before you flip the card. Retrieving it from memory is what builds recall, reading it again is not.

DefineArray
AnswerA fixed size collection of items of the same type in contiguous memory, accessed by index.
DefineRecord
AnswerA structure holding a fixed set of named fields, which may be of different types.
DefineTuple
AnswerAn ordered collection that cannot be changed after creation.
DefineStack
AnswerA last in first out structure supporting push and pop.
DefineQueue
AnswerA first in first out structure supporting enqueue and dequeue.
DefineCircular queue
AnswerA queue whose pointers wrap around using modulo arithmetic to avoid wasting space.
DefineLinked list
AnswerA structure of nodes each holding data and a pointer to the next node.
DefineGraph
AnswerA set of vertices connected by edges, which may be directed or weighted.

Reach the top grade on this topic

  • Justify a data structure choice by the operations the scenario performs most
  • Compare arrays and linked lists on access time and insertion cost, with the reason for each
  • Explain adjacency matrix against adjacency list in terms of sparse and dense graphs
  • Know that in order traversal of a BST yields sorted output, and that a sorted insertion order degenerates it
  • Explain collision resolution and why the load factor triggers rehashing

Mistakes that cost marks here

Avoid these
  • Saying a linked list is faster than an array. Access is slower, insertion in the middle is faster.
  • Forgetting that a binary search tree degenerates to a linked list if data is inserted in sorted order.
  • Confusing the traversal orders. In order gives sorted output from a BST.
  • Using an adjacency matrix for a sparse graph, which wastes enormous amounts of memory.
  • Saying hash tables are always constant time. That is the average case, and it depends on the load factor and the hash function.
Fun fact

A hash table gives average constant time lookup regardless of size, which is why a dictionary with ten items and one with ten million behave almost identically. Everything depends on the hash function distributing keys evenly.

Knowledge check

0 of 10 answered
1Which structure operates on a last in first out basis?
2What is the main advantage of a circular queue over a linear queue?
3What is the key advantage of a linked list over an array?
4Which traversal of a binary search tree outputs values in ascending order?
5When does a binary search tree degenerate to linear performance?
6Which graph representation is better for a sparse graph?
7What is a hash collision?
8What does the load factor of a hash table measure?
9Which structure is most appropriate for a print spooler?
10What is stored in each node of a linked list?
Score 0 / 10

Exam-style questions

Five written questions in the style of the real paper. Write a full answer, then let the marker check it against the mark scheme.

24 marks
1Explain the difference between a stack and a queue, giving one use for each.4 marks
Explain

Mark scheme0 / 4
  • LA stack is last in first out
  • LA queue is first in first out
  • LGives a valid stack use such as the call stack or undo
  • LGives a valid queue use such as a print spooler or scheduling
Model answer

A stack operates on a last in first out basis, so the most recently pushed item is the first one removed by a pop, and only the top of the stack is directly accessible. A queue operates on a first in first out basis, so items are dequeued in the order they were added and access is at both ends, adding at the rear and removing from the front. A stack is used for the call stack in a running program, where each function call pushes a return address and local variables that must be restored in exactly the reverse order as calls return, and it is equally the natural structure for undo functionality. A queue is used for a print spooler, where jobs must be printed in the order they were submitted so that no user is unfairly delayed by someone who submitted later.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
2Compare an array and a linked list.6 marks
Compare

Mark scheme0 / 6
  • LAn array occupies contiguous memory, a linked list does not
  • LAn array has a fixed size, a linked list can grow and shrink dynamically
  • LArray elements are accessed directly by index in constant time
  • LA linked list must be traversed from the start, so access is slower
  • LInserting into the middle of an array requires shifting subsequent elements
  • LInserting into a linked list only requires changing pointers
Model answer

An array stores its elements in a contiguous block of memory, all of the same type and size, which allows the address of any element to be calculated directly from the base address and the index, giving constant time access to any position. Its size is fixed when it is created, so it cannot grow, and inserting an element into the middle requires every subsequent element to be shifted one position along, which on a large array is extremely expensive. A linked list stores each element in a node that may be located anywhere in memory, together with a pointer to the next node, so the list can grow and shrink at run time as nodes are created and destroyed. The cost of that flexibility is access time: there is no way to calculate the address of the nth item, so the list must be traversed from the head following pointers, which takes time proportional to the position. In exchange, inserting or deleting in the middle requires only that two pointers be reassigned, with no data movement at all. Each node also carries the memory overhead of its pointer, which an array does not. The choice therefore depends on the workload: arrays suit data that is read by index and rarely restructured, while linked lists suit data that is frequently inserted into and removed from.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
3Explain how a hash table achieves constant time lookup and describe one method of resolving collisions.5 marks
Explain

Mark scheme0 / 5
  • LA hash function converts the key into an array index
  • LThe item is stored at and retrieved from that index directly
  • LNo search of the structure is required, so lookup time does not depend on the number of items
  • LA collision occurs when two keys hash to the same index
  • LDescribes chaining or linear probing as a resolution method
Model answer

A hash table achieves fast lookup by applying a hash function to the key, which deterministically converts it into an index within the underlying array. The item is stored at that index when inserted, and on retrieval the same hash function is applied to the search key to produce the same index, so the item is found by a single direct array access without searching any part of the structure. Because the position is calculated rather than searched for, the time taken does not grow as the number of stored items increases, giving average constant time performance. A collision occurs when two different keys produce the same index. One resolution method is separate chaining, in which each slot in the array holds a linked list rather than a single item, and any keys hashing to that slot are appended to its list. Lookup then hashes to the slot and searches only that short list, and performance degrades gracefully as the table fills. The alternative, linear probing, stores the colliding item in the next free slot instead, which avoids extra structures but tends to produce clusters of occupied slots that lengthen future searches.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
4A program must repeatedly find a customer record by their unique customer ID from several million records. Recommend a data structure and justify your choice.5 marks
Justify

Mark scheme0 / 5
  • LRecommends a hash table
  • LThe customer ID is a unique key suited to hashing
  • LThe hash function calculates the position so no search is needed
  • LLookup is average constant time regardless of the number of records
  • LCompares favourably with alternatives such as a linear search or a tree
Model answer

A hash table is the right structure here. Each customer has a unique ID, which is precisely the kind of key a hash table is designed around, and the required operation is repeated lookup by that key rather than ordered traversal or range queries. The hash function converts the customer ID directly into an array index, so the record is retrieved by a single array access with no searching whatsoever, and crucially the time taken does not grow as the number of records increases, so retrieval from ten million records is essentially as fast as from ten. The alternatives are markedly worse for this workload. A linear search through an unsorted array would examine on average half of the several million records for every lookup, which is completely impractical at any volume of queries. A binary search tree would give logarithmic performance, requiring around twenty three comparisons for eight million records, which is far better than linear but still substantially slower than a single calculated access, and it would degrade badly if the IDs happened to be inserted in sorted order. The hash table's costs are that it does not maintain any useful ordering and that performance depends on a good hash function and on rehashing when the load factor rises, but since the requirement is purely lookup by unique key, neither of those is a meaningful drawback.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
5Explain the difference between an adjacency matrix and an adjacency list, and state when each is preferable.4 marks
Explain

Mark scheme0 / 4
  • LAn adjacency matrix is a two dimensional array recording whether each pair of vertices is connected
  • LAn adjacency list stores for each vertex a list of the vertices it connects to
  • LA matrix uses space proportional to the square of the number of vertices regardless of edges
  • LA list is preferable for sparse graphs and a matrix for dense graphs or frequent edge checks
Model answer

An adjacency matrix represents a graph as a two dimensional array in which the entry at row i and column j records whether an edge exists from vertex i to vertex j, and in a weighted graph holds the weight of that edge. An adjacency list instead stores, for each vertex, a list of the vertices it is directly connected to. The essential difference is space. A matrix requires storage proportional to the square of the number of vertices whether or not the edges exist, so a graph of ten thousand vertices needs a hundred million entries even if only a few thousand edges are present. An adjacency list uses space proportional to the number of edges actually present. A matrix is therefore preferable for dense graphs, where most possible edges exist so little space is wasted, and where the ability to check whether a specific edge exists in constant time matters. An adjacency list is preferable for sparse graphs, which is the far more common case in practice, since real road networks, social networks and dependency graphs all have far fewer edges than the theoretical maximum.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
Machine mark 0 / 24