Everything on the site.

Big-O notationAlgorithms · Count the steps in real loops, then compare n, n log n, n² and 2ⁿ on a live chart.RecursionAlgorithms · Watch frames push and pop on the call stack for factorial and Fibonacci.BFS vs DFSAlgorithms · A queue against a stack: draw a graph and see which order each search visits it in.Sorting algorithmsAlgorithms · Seven sorts on the same input, with comparison, swap and write counts side by side.Binary searchAlgorithms · Halve the range, probe the middle, repeat: with lo, mid and hi drawn on the array.Sets, relations and functionsDiscrete maths · Shade any set expression on a Venn diagram and test a relation for its properties.Proof by inductionDiscrete maths · Four worked proofs revealed one step at a time, and a broken one to diagnose.CombinatoricsDiscrete maths · An exact nPr and nCr calculator, and a Pascal’s triangle that shows its own addition rule.Boolean algebraDiscrete maths · The laws, De Morgan, and normal forms, with a truth-table generator built in.Finite-state machinesTheory · Build a DFA in a table, see it drawn, and run strings through it one symbol at a time.Domain theoryTheory · Why recursion needs least fixed points, and how CPOs, Scott continuity and powerdomains supply them.Truth table generatorTools · Expression in, truth table out: with DNF, CNF, a minimal form and LaTeX.Graph traversal visualiserTools · Draw a graph, then animate BFS, DFS and Dijkstra with the frontier shown.Recursion tree visualiserTools · Paste a recursive function or a recurrence and see its call tree and call count.Gradient descentML maths · Drag the starting point, set the learning rate, and watch it converge or blow up.Vectors and embeddingsML maths · Bend the plane with a 2×2 matrix and measure how close toy word vectors are.Softmax and cross-entropyML maths · Edit the logits and watch the probabilities, the loss and the gradient update live.AttentionML maths · Q, K and V for three tokens, a live score heatmap, and the weighted sum of values.Formatting a CS paper in LaTeXLaTeX · Page limits, \documentclass, front matter, theorem environments and the bibliography.Camera-ready checklistLaTeX · Fonts embedded, PDF/A, copyright form, source bundle, and why final versions get rejected.LaTeX templatesLaTeX · Where the official classes live, plus a minimal article template you can copy.AlgorithmsSection · Step-through visualisations of sorting, searching, recursion, graph traversal and Big-O growth, each with pseudocode that highlights the line being run.Discrete mathsSection · Sets, relations and functions, proof by induction, counting, and Boolean algebra, explained with worked examples and small interactive checkers.TheorySection · Finite-state machines, automata and the mathematical semantics of programming languages, explained from first principles.ML mathsSection · Gradient descent, vectors and embeddings, softmax and cross-entropy, and attention, each with a formula, a worked numeric example and a live version.ToolsSection · A truth-table generator with CNF, DNF and LaTeX output, a graph-traversal visualiser for BFS, DFS and Dijkstra, and a recursion-tree visualiser.LaTeXSection · How to format a CS conference or workshop paper in LaTeX, a camera-ready checklist, and a minimal template you can adapt.
Algorithms

Sorting algorithms, animated and compared

Sorting is the most studied problem in computer science, and a good place to learn how algorithms are compared. Run seven classic sorts on the same numbers, step by step, and watch how many comparisons, swaps and writes each one needs.

Interactive: Sorting visualiser with seven algorithms and a comparison tableUpdated

Every sorting algorithm below takes a list of numbers and puts it in increasing order. They differ in how: which pairs they compare, how they move values, how much extra memory they need, and how their running time grows. The visualiser highlights the line of pseudocode being executed and explains each step in words. Change the input to see how the algorithms react to sorted, reversed and repetitive data.

Sorting visualiserPick an algorithm, edit the values, then press play or step through.

  • Comparing
  • Swapping
  • Writing
  • Pivot / heap root
  • Key / current minimum
  • In final place

Pseudocode

    Counters

    0Comparisons
    0Swaps
    0Writes

    This algorithm

    Compare all seven algorithms on this input
    AlgorithmComparisonsSwapsWritesWorst caseStable?

    A swap exchanges two entries; a write stores one value (merge, insertion and counting sort move values by writes). Counting sort never compares two elements, which is how it beats the n log n lower bound for comparison sorts.

    The seven algorithms

    AlgorithmBestAverageWorstExtra spaceStable
    Bubble sortΘ(n)Θ(n²)Θ(n²)Θ(1)Yes
    Insertion sortΘ(n)Θ(n²)Θ(n²)Θ(1)Yes
    Selection sortΘ(n²)Θ(n²)Θ(n²)Θ(1)No
    Merge sortΘ(n log n)Θ(n log n)Θ(n log n)Θ(n)Yes
    QuicksortΘ(n log n)Θ(n log n)Θ(n²)Θ(log n) stack on averageNo
    HeapsortΘ(n log n)Θ(n log n)Θ(n log n)Θ(1)No
    Counting sortΘ(n + m)Θ(n + m)Θ(n + m)Θ(m) for the countsYes

    Bubble sort

    Bubble sort walks along the array swapping any neighbouring pair that is out of order. After the first pass the largest value has “bubbled” to the end; after the second, the two largest are in place; and so on. If a whole pass makes no swaps, the array is sorted and it can stop early, which is why its best case is linear. It is easy to understand and almost never the right choice: it makes n(n−1)/2n(n-1)/2 swaps on reversed input, one for every out-of-order pair.

    Insertion sort

    Insertion sort grows a sorted prefix. It lifts out the next value (the key), slides every larger value in the prefix one place to the right, and drops the key into the gap. On nearly sorted input each key moves only a little, so insertion sort is fast there, and it is the standard choice for short arrays inside bigger algorithms.

    Worked example: insertion sort on [7, 3, 5, 1]

    StepArray afterWhat happened
    start7 3 5 1—
    i = 1, key 33 7 5 17 > 3, shift 7 right; drop 3 at index 0
    i = 2, key 53 5 7 17 > 5, shift; 3 ≤ 5, stop; drop 5 at index 1
    i = 3, key 11 3 5 77, 5 and 3 are all > 1, shift each; drop 1 at index 0

    That took 6 comparisons. Type 7, 3, 5, 1 into the visualiser and choose insertion sort to step through the same run.

    Selection sort

    Selection sort scans the unsorted part for its minimum and swaps it to the front. It always makes exactly n(n−1)/2n(n-1)/2 comparisons, whatever the input, but never more than n−1n - 1 swaps. That makes it a reasonable choice only when writing to memory is much more expensive than reading.

    Merge sort

    Merge sort is divide and conquer: split the array in half, sort each half recursively, and merge the two sorted halves by repeatedly taking the smaller front element. Merging nn elements costs at most n−1n - 1 comparisons, and the halving gives log⁡2n\log_2 n levels, so the total is O(nlog⁡n)O(n \log n) on every input. The price is a buffer of size nn. Merge sort is stable, and its sequential access pattern suits linked lists and data on disk.

    Quicksort

    Quicksort, published by Tony Hoare in 1962, also divides and conquers, but does the work before recursing. It picks a pivot and partitions the array so that smaller values come before it and the rest after; the pivot is then in its final place, and the two sides are sorted independently. The visualiser uses the simple Lomuto partition with the last element as pivot.

    When pivots split the array roughly in half, quicksort takes O(nlog⁡n)O(n \log n) time and, in practice, is usually the fastest of the comparison sorts because its inner loop is tight and cache-friendly. When pivots are consistently the smallest or largest value, each partition removes only one element and it degrades to O(n2)O(n^2). With the last element as pivot that happens on input that is already sorted: try the “Reversed” button, then sort the sorted result again. Real implementations avoid this by choosing the pivot randomly or as the median of three samples.

    Heapsort

    Heapsort first rearranges the array into a max-heap, a binary tree stored in the array where A[i]A[i] is at least as large as its children A[2i+1]A[2i+1] and A[2i+2]A[2i+2]. The maximum is then at the root. It swaps the root to the end, shrinks the heap by one, and sifts the new root down to restore the heap property. It guarantees O(nlog⁡n)O(n \log n) time with constant extra space, but jumps around memory, so it is usually slower than quicksort in practice.

    Counting sort

    Counting sort never compares two elements. It counts how many times each value occurs, then writes the values back in order. For nn integers between 0 and mm it takes O(n+m)O(n + m) time, so it beats every comparison sort when the range is small. It is the building block of radix sort, which sorts numbers digit by digit.

    Stability

    A sort is stable if elements that compare equal keep their original order. That matters when you sort records by one field after another. Sort a list of people by first name, then stably by surname, and people with the same surname end up in first-name order. Merge, insertion, bubble and counting sort are stable as written here; selection sort, quicksort and heapsort can move an element past an equal one.

    Why nlog⁡nn \log n is the limit for comparison sorts

    Any algorithm that learns about the order only by comparing pairs can be drawn as a binary decision tree: each internal node is a comparison, each leaf an output order. To sort correctly it needs a different leaf for each of the n!n! possible orderings of the input. A binary tree with n!n! leaves has height at least log⁡2n!\log_2 n!, so some input forces at least that many comparisons, and

    log⁡2n!=nlog⁡2n−nlog⁡2e+O(log⁡n)=Θ(nlog⁡n).\log_2 n! = n\log_2 n - n\log_2 e + O(\log n) = \Theta(n \log n).

    For 12 elements, 12!=479,001,60012! = 479{,}001{,}600 and log⁡212!≈28.8\log_2 12! \approx 28.8, so every comparison sort needs at least 29 comparisons on its worst 12-element input. Open the comparison table under the visualiser with the input 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 to see where each algorithm lands. Counting sort escapes the bound because it is not a comparison sort: it uses the values themselves as array indices.

    What real libraries use

    Production sorts are hybrids that combine the strengths above.

    • Timsort (Tim Peters, 2002) finds runs that are already in order, extends short ones with insertion sort, and merges them. It is stable and very fast on partly sorted data. Python’s list.sort, Java’s sort for object arrays, and V8’s Array.prototype.sort (used in Chrome and Node.js) are Timsort or descendants of it.
    • Introsort starts as quicksort, switches to heapsort if the recursion gets suspiciously deep, and finishes small ranges with insertion sort, which guarantees O(nlog⁡n)O(n \log n). It is the usual implementation of C++’s std::sort.
    • Dual-pivot quicksort partitions around two pivots at once; Java uses it for arrays of primitive values.
    Rule of thumb Use your language’s built-in sort. Reach for a specific algorithm when you know something special: the data is almost sorted (insertion sort or Timsort), the keys are small integers (counting or radix sort), or you need a guaranteed worst case (merge sort or heapsort).

    References

    1. C. A. R. Hoare, “Quicksort”, The Computer Journal 5(1), 1962. doi:10.1093/comjnl/5.1.10
    2. J. W. J. Williams, “Algorithm 232: Heapsort”, Communications of the ACM 7(6), 1964.
    3. D. E. Knuth, The Art of Computer Programming, Volume 3: Sorting and Searching, 2nd ed., Addison-Wesley, 1998.
    4. “Sorting algorithm”, Wikipedia.