Algorithms

Technology — James William Steven Parker

An algorithm is a finite, precisely defined sequence of computational steps used to transform given inputs into desired outputs or to accomplish a specified computational task. An algorithm is more than an informal idea for solving a problem because its operations must be sufficiently well specified that they can be carried out systematically, whether by a person, a computer program, a mathematical procedure, or another computational system.

Algorithms may accept zero, one, or many inputs, may produce one or more outputs, and may involve decisions, repetition, recursion, data access, arithmetic, comparisons, communication, or other operations. Classical descriptions commonly emphasise finiteness, definiteness, effective computability, input, output, and correctness. An algorithm can therefore exist independently of a particular programming language or hardware implementation. The same algorithm may be expressed as pseudocode, mathematical notation, a flowchart, structured English, or source code, with implementation details varying while the underlying computational method remains substantially the same.

Algorithms have a long intellectual history predating electronic computers. The word is derived through medieval Latin and European mathematical usage from the name of the Persian mathematician Muhammad ibn Musa al-Khwarizmi, whose works helped transmit systematic methods of arithmetic. Earlier mathematical cultures also developed systematic procedures for calculations, including methods resembling the Euclidean algorithm for computing greatest common divisors.

In the twentieth century, the concept became central to mathematical logic and theoretical computer science through formal models such as Turing machines, lambda calculus, recursive functions, and related definitions of effective computation. The development of electronic computers transformed algorithms from primarily mathematical procedures into executable computational artefacts capable of operating at enormous scale. Modern algorithms now underpin operating systems, databases, compilers, search engines, networks, artificial intelligence, cryptography, scientific computing, graphics, and virtually every software system.

Algorithms can be classified according to the techniques they employ and the problems they solve. Iterative algorithms repeatedly execute operations, whereas recursive algorithms define a solution partly in terms of smaller instances of the same problem. Divide-and-conquer algorithms divide a problem into subproblems, solve those subproblems, and combine their results. Greedy algorithms make locally optimal choices according to a specified strategy, dynamic programming stores solutions to overlapping subproblems, and backtracking systematically explores possible choices while abandoning unsuccessful partial solutions.

Randomised algorithms deliberately use random choices, sometimes to improve expected performance or simplify implementation. Deterministic algorithms produce the same computational behaviour for identical inputs under identical conditions, whereas nondeterministic models describe computational possibilities useful in complexity theory. Online algorithms process information as it arrives, while offline algorithms can examine the complete input before computing a result.

Correctness is a fundamental property of an algorithm and is distinct from performance. An algorithm is correct when it produces the specified result for every input within its defined domain, subject to the assumptions of its specification. Correctness can be established using informal reasoning, mathematical proofs, loop invariants, induction, preconditions and postconditions, exhaustive testing for limited domains, formal verification, model checking, or combinations of these approaches.

Partial correctness means that whenever an algorithm terminates, its result satisfies the specification, whereas total correctness additionally requires proof of termination. Edge cases are particularly important because an algorithm that works on ordinary inputs may fail for empty collections, duplicate values, maximum or minimum representable values, malformed input, integer overflow, disconnected graphs, or other boundary conditions. A precise specification is therefore essential because correctness cannot meaningfully be assessed without knowing what the algorithm is required to accomplish.

The efficiency of an algorithm is commonly evaluated in terms of resources consumed as a function of input size. Time complexity describes how the amount of computation grows, while space complexity describes additional memory requirements. Big O notation provides an asymptotic upper-bound classification commonly used to describe growth rates, while Big Theta expresses an asymptotically tight bound and Big Omega expresses an asymptotic lower bound. Typical growth classes include constant, logarithmic, linear, linearithmic, quadratic, polynomial, exponential, and factorial growth.

These abstractions allow algorithms to be compared independently of particular processor speeds or implementation languages, although real performance also depends on constants, memory hierarchy, cache behaviour, input distribution, parallelism, compiler optimisation, storage latency, and other factors. Worst-case, average-case, best-case, amortised, and expected analyses answer different questions and should not be treated as interchangeable descriptions of performance.

Algorithm design involves selecting computational strategies that satisfy functional requirements while balancing correctness, efficiency, simplicity, maintainability, robustness, and resource constraints. A design process commonly begins by specifying the problem, identifying input and output requirements, establishing constraints, selecting suitable representations, decomposing the problem, choosing an algorithmic paradigm, proving or testing correctness, analysing complexity, implementing the method, and evaluating its behaviour.

Design choices are often inseparable from data representation because an operation that is efficient with one data structure may be inefficient with another. For example, membership testing can have different costs depending on whether data is held in an unsorted array, balanced search tree, hash table, or specialised index. Practical algorithm engineering also considers exceptional cases, concurrency, numerical precision, external storage, security, fault tolerance, and predictable resource usage.

Algorithms are used throughout computing and are often embedded inside larger systems rather than exposed directly to users. A navigation application may use algorithms for shortest paths, map matching, traffic estimation, and route optimisation. A database system uses algorithms for indexing, query optimisation, joining relations, sorting records, transaction processing, and storage management. Compilers use algorithms for lexical analysis, parsing, optimisation, register allocation, and code generation. Operating systems employ scheduling, memory allocation, caching, synchronisation, and resource-management algorithms.

Machine-learning systems depend on optimisation, numerical linear algebra, sampling, inference, and learning algorithms. In cybersecurity, algorithms provide encryption, hashing, authentication, signature generation, and random-number generation. The same general algorithmic idea can consequently appear in very different application domains, with domain-specific constraints determining the appropriate implementation and evaluation criteria.

An important distinction is between an algorithm and a program. An algorithm is an abstract computational procedure, whereas a program is an implementation expressed in a programming language and intended to execute within a particular environment. A program can contain multiple algorithms, libraries, data structures, interfaces, and system interactions, and one algorithm can have many program implementations.

Algorithms also differ from heuristics: an algorithm generally specifies a systematic procedure with defined correctness properties, while a heuristic is a practical strategy that may sacrifice guaranteed optimality or completeness in exchange for speed, simplicity, or usefulness. Algorithms do not necessarily produce exact numerical answers; approximation algorithms deliberately produce solutions within specified error or quality bounds, while probabilistic algorithms may provide guarantees expressed in terms of probability. Consequently, understanding an algorithm requires considering not only its steps but also its specification, assumptions, correctness guarantees, resource requirements, computational model, and intended operating context.