Fundamental Algorithms – Order of Growth
Learning Objectives & Overview
Understand why analysing algorithm performance matters when processing complex problems or large datasets.
Be able to:
Define and interpret “order of growth” for algorithms.
Express time-complexity using Big-O notation.
Recognise, derive and compare common growth-rate classes.
Analyse best-, average- and worst-case complexities for classic search/sort algorithms.
Apply complexity knowledge to algorithm choice, optimisation and exam questions.
The Need for Order of Growth
Even slow algorithms finish quickly on very small inputs; the real concern is performance as input size becomes large.
Running the same device with different algorithms can lead to markedly different resource consumption (time, memory).
Order-of-growth analysis allows:
Prediction of scalability.
Fair comparison of competing solutions on identical hardware.
Identification of bottlenecks before deployment.
Order of Growth & Complexity Measures
Rough measure of resources as .
Two primary resources:
Time complexity – number of primitive operations / comparisons / steps.
Space complexity – memory required (excluded from the syllabus here).
We generally analyse worst-case unless otherwise stated; it provides an upper bound for all inputs.
Big-O Notation
Mathematical convention: = the set of functions that grow no faster (within a constant factor) than for sufficiently large .
Ignore constants and lower-order terms; only the highest-order term dictates growth rate.
Example interpretations:
constant time (independent of ).
linear growth (proportional to ).
scaled logarithmic.
quadratic.
exponential.
Common Growth-Rate Functions
Ordered from slowest growth to fastest:
Constant
Logarithmic
Linear
Linear-log
Quadratic
Polynomial (k>2)
Exponential
Numerical Illustration (selected values)
Table excerpt (operations required vs ):
: , , , .
: , , , .
Key takeaway: exponential functions explode rapidly; algorithms in that class are infeasible for large .
Worked Exercise – Counting Comparisons in a While Loop
word = input("Enter a word: ")
posn = 0
while posn < len(word):
print(word[posn])
posn += 1
Each iteration performs one comparison (
posn < len(word)), plus one final false check.For input of length : total comparisons → .
Specific cases:
"magic" (5 chars): comparisons.
"hi there" (8 chars): comparisons.
Example: is_prime Function
FOR i = 2 TO n
IF n MOD i = 0 THEN RETURN FALSE
RETURN TRUE
Worst case: is prime ⇒ loop executes iterations.
If each iteration costs constant , total .
Discard constants: (linear).
Linear Search Complexity
Best case: first element matches ⇒ comparison ⇒ .
Worst case: item at last position or absent ⇒ comparisons ⇒ .
Binary Search Complexity
Works on sorted list by halving the search interval.
Best case: target equals middle element ⇒ .
Worst case derivation:
Array length after halvings: ⇒ .
Comparisons per level: .
Total ⇒ .
Note: base-2 logarithm is required; differs.
Bubble Sort Complexity
Worst case (reverse order):
Passes: , each with comparisons.
Total comparisons ⇒ .
Best case (already sorted):
Single pass, comparisons ⇒ .
Insertion Sort Complexity
Worst case (descending input when ascending desired):
Comparisons + swaps: ⇒ .
Best case (already sorted):
Only comparisons ⇒ .
Quick Sort Complexity
Worst case (pivot always min or max):
Comparisons: ⇒ .
Best / average case (pivot = median or chosen randomly):
Levels: .
Comparisons per level: .
Total: ⇒ .
Pivot selection notes:
True median yields optimal split but costs linear time to find.
Random pivot greatly reduces probability of worst case; expected .
For nearly-sorted data, insertion sort may outperform quicksort (best case vs ).
Merge Sort Complexity
Divide list until size , then merge.
Recurrence: .
Solving: ⇒ .
Characteristic features:
Same complexity for best, average, worst cases because splitting always proceeds.
Performance insensitive to initial order.
Not in-place: requires extra memory for merging.
Advantages & Disadvantages of Sorting Algorithms
Bubble Sort
+ Simplicity, good for testing if list already sorted (best ).
- Very slow on large/random data (), rarely used in practice.
Insertion Sort
+ Simple, efficient for very small or nearly-sorted datasets, stable.
- worst case, beaten by more advanced algorithms on large data.
Quick Sort
+ Fastest general-purpose in-place sort, low memory, average .
- worst case, unstable, not ideal for tiny arrays.
Merge Sort
+ Guaranteed , stable, optimal worst case.
- Needs extra space; copying overhead may hurt performance.
Choosing a Sorting Method – Practical Criteria
Number of records.
Record length (long records may favour methods that move pointers rather than data).
Availability of main memory (internal vs external sort).
Existing order: nearly-sorted arrays benefit most from insertion or bubble sort variants.
Summary Table
Algorithm | Best | Worst |
|---|---|---|
Bubble Sort | ||
Insertion Sort | ||
Quick Sort | ||
Merge Sort |
Additional qualitative analysis:
Bubble: best for almost sorted.
Insertion: generally preferable to Bubble; still special-case.
Quick: fastest on large random data if stability not required.
Merge: best theoretical guarantees but uses extra memory.
Worksheet / Exam-Style Problems
1. Recursive Fibonacci
Code:
IF n <= 1 RETURN n
ELSE RETURN fib(n-1)+fib(n-2)
(a) Time complexity: where ≈ (exponential).
(b) Explanation: each call spawns two more calls except at base cases; call tree resembles binary tree of height ⇒ about total calls.
(c) Optimisation: memoisation / dynamic programming stores intermediate Fibonacci numbers, reducing complexity to time and space (or space with iterative solution).
2. Searching 1,000,000 Sorted Emails
(i) Binary search preferred: comparisons vs linear search’s .
(ii) If new emails are appended unsorted at the end, the list becomes partially ordered. Options:
Maintain full sort then use binary search (requires periodic re-sort).
Keep as hybrid: binary search on sorted prefix, linear search remaining tail.
If disorder grows, revert to full linear search or re-sort.
3. Practical Timing Task (A-Level P2)
Implement functions:
task2_2– insertion sort.task2_3– quicksort.
Use Python
timeitto measure on three text files.Expected empirical orders of growth:
Insertion sort runtime ∝ (doubling input roughly quadruples time).
Quicksort runtime ∝ (doubling input < double time).
Discuss anomalies: quicksort slower on tiny or nearly-sorted files where insertion shines.
These bullet-point notes encapsulate all definitions, derivations, numeric examples, algorithm analyses, comparisons, and worksheet prompts required to replace the original 18-page transcript.