An Abstract Data Type (ADT) describes what a data structure does, not how it does it.
push, pop, insert, delete).The ADT specification is independent of the concrete representation (array, linked list, tree, …).
Typical ADTs in the Cambridge (9618) syllabus:
Target ADT: push(x), pop(), top()
push(x):L.append(x) // add at the end of the list
pop():
if L.isEmpty() then
raise EmptyStructureError
return L.removeLast() // remove and return last element
top():
if L.isEmpty() then
raise EmptyStructureError
return L.get(L.size()‑1) // read without removing
append and removeLast are O(1) amortised (array may need occasional resizing).Target ADT: enqueue(x), dequeue(), front()
enqueue(x):S1.push(x)
dequeue():
if S2.isEmpty() then
while not S1.isEmpty() do
S2.push(S1.pop()) // transfer and reverse order
if S2.isEmpty() then
raise EmptyStructureError
return S2.pop()
front():
if S2.isEmpty() then
while not S1.isEmpty() do
S2.push(S1.pop())
if S2.isEmpty() then
raise EmptyStructureError
return S2.top()
enqueue and dequeue. The occasional O(n) transfer is spread over many operations.Target ADT: insert(x), deleteMin(), peekMin()
insert(x):heap.append(x) // place at next free position
heapifyUp(heap.size()‑1) // restore heap order
deleteMin():
if heap.isEmpty() then
raise EmptyStructureError
min ← heap[0]
heap[0] ← heap.removeLast() // move last element to root
heapifyDown(0) // restore heap order
return min
peekMin():
if heap.isEmpty() then
raise EmptyStructureError
return heap[0]
insert and deleteMin; O(1) for peekMin.Target ADT: put(key, value), get(key), remove(key)
hash(key):return (some deterministic function of key) mod m // m = table size
put(key, value):
i ← hash(key)
while table[i] ≠ empty and table[i].key ≠ key do
i ← (i + 1) mod m // linear probing
table[i] ← (key, value)
get(key):
i ← hash(key)
while table[i] ≠ empty do
if table[i].key = key then
return table[i].value
i ← (i + 1) mod m
raise KeyError
remove(key):
i ← hash(key)
while table[i] ≠ empty do
if table[i].key = key then
table[i] ← deletedMarker
return
i ← (i + 1) mod m
raise KeyError
// iterative versionlinearSearchIter(arr, key):
for i ← 0 to arr.length‑1 do
if arr[i] = key then
return i
return -1 // not found
// recursive version
linearSearchRec(arr, key, i):
if i = arr.length then return -1
if arr[i] = key then return i
return linearSearchRec(arr, key, i+1)
binarySearch(arr, key):low ← 0; high ← arr.length‑1
while low ≤ high do
mid ← (low + high) ÷ 2
if arr[mid] = key then return mid
else if arr[mid] < key then low ← mid + 1
else high ← mid – 1
return -1
insertionSort(arr):for i ← 1 to arr.length‑1 do
key ← arr[i]
j ← i‑1
while j ≥ 0 and arr[j] > key do
arr[j+1] ← arr[j]
j ← j‑1
arr[j+1] ← key
bubbleSort(arr):repeat
swapped ← false
for i ← 0 to arr.length‑2 do
if arr[i] > arr[i+1] then
swap(arr[i], arr[i+1])
swapped ← true
until not swapped
swapped flag)When comparing any two algorithms (search, sort, or ADT‑based), discuss:
| Algorithm | Worst‑case | Average‑case | Best‑case | Extra Memory | Notes |
|---|---|---|---|---|---|
| Linear Search | O(n) | O(n) | O(1) (first element) | O(1) iterative / O(n) recursive | Works on unsorted data. |
| Binary Search | O(log n) | O(log n) | O(log n) | O(1) iterative / O(log n) recursive | Array must be sorted. |
| Insertion Sort | O(n²) | O(n²) | O(n) | O(1) | Stable, adaptive. |
| Bubble Sort | O(n²) | O(n²) | O(n) | O(1) | Stable; “swapped” flag gives O(n) best case. |
| ADT Implemented | Underlying ADT | Operation | Worst‑case Time | Amortised Time | Extra Memory |
|---|---|---|---|---|---|
| Stack | Dynamic List (array) | push | O(1) amortised (occasional resize O(n)) | O(1) | O(n) |
| pop | O(1) | O(1) | O(n) | ||
| top | O(1) | O(1) | O(n) | ||
| Queue | Two Stacks | enqueue | O(1) | O(1) | O(n) |
| dequeue | O(n) when S2 empty | O(1) amortised | O(n) | ||
| front | O(n) when transfer needed | O(1) amortised | O(n) | ||
| size | O(1) | O(1) | O(n) | ||
| Priority Queue | Binary Heap (array) | insert | O(log n) | O(log n) | O(n) |
| deleteMin / deleteMax | O(log n) | O(log n) | O(n) | ||
| peekMin / peekMax | O(1) | O(1) | O(n) |
push appends, pop removes that same element, preserving LIFO order.S1 in arrival order. When S2 is empty, all elements are transferred, reversing their order so the oldest element becomes the top of S2. Subsequent dequeue operations remove from S2, guaranteeing FIFO behaviour.peekMin reads this element; deleteMin removes it and restores the invariant, matching the abstract specification.put, get and remove locate the correct bucket, preserving the “key → value” relationship.pop():if L.isEmpty() then
raise EmptyStructureError("Attempt to pop from an empty stack")
return L.removeLast()
In an exam answer it is sufficient to state that an appropriate error is raised (or a special sentinel value returned) when an operation is applied to an empty structure or an invalid key.
Your generous donation helps us continue providing free Cambridge IGCSE & A-Level resources, past papers, syllabus notes, revision questions, and high-quality online tutoring to students across Kenya.