Adjacency list Created 2026-10-13 Updated 2026-10-20
An adjacency list represents a graph by keeping, for each vertex , a collection of the vertices reached by its outgoing edges. An array indexed by vertex identifiers can locate each collection; the collection itself may use a linked list or an array. In an undirected graph, each nonloop edge supplies an entry at both endpoints.[ref]
For a worked example, take the simple graph
where denotes the unordered pair . Its adjacency lists, displayed in label order, are
Thus has three neighbours, although the graph has six vertices. Its list contains exactly the destinations available for a single step from ; no slots are reserved there for . The fourteen neighbour entries represent seven edges, with appearing as in 's list and as in 's list. The label order makes the example easy to read; an adjacency list need not be sorted.
Figure 1.
Seven undirected edges and their fourteen adjacency list entries
. Details.
The useful idea is to store existing connections explicitly. Neighbour enumeration can then follow exactly the possible next steps, which is what breadth-first search and depth-first search need. In a sparse graph, most pairs of vertices have no edge; adjacency lists avoid reserving a separate adjacency matrix entry for every such absence. Whether this saves work depends on the question: neighbour enumeration and testing one proposed edge have different costs.
Write and . Suppose each vertex identifier, list descriptor, link and optional edge weight occupies a constant number of machine words, and indexed array access and identifier comparison take constant time. There are list descriptors and directed, or undirected, neighbour entries. Hence adjacency lists use machine words in Big O notation. A full adjacency matrix has entries, regardless of . These are counts under a storage model, not fixed byte sizes.[ref]
Our undirected example has six list descriptors and fourteen neighbour entries, versus thirty-six full adjacency matrix entries. The numbers and count different kinds of logical items: they do not prove a particular byte saving. A linked list also needs links; an array may have unused capacity. Storing only half of a symmetric matrix changes its exact count while leaving quadratic growth. If identifiers or weights require growing numbers of machine words, their size must be included in the space complexity.
Figure 1.
Adjacency matrix storage and queries compared with adjacency lists on the same six-vertex graph
. Details.
An unsorted adjacency list answers "does the edge exist?" by linear search through . In the worst case it inspects all entries, giving time, or for . Even if is absent, an uninspected entry could still contain it, so arbitrary lists require the whole scan. On our example, looking for in 's list compares with and fails after three comparisons. A full adjacency matrix instead answers from its single entry in time.[ref]
Different promises change the query. A sorted array of neighbour identifiers permits binary search in time, but maintaining order after insertion may require shifting entries. A per-vertex hash table permits expected constant-time membership under the hashing and load assumptions of that data structure; it does not give that guarantee to an arbitrary adjacency list. A stored list length can likewise make a vertex degree query constant-time even though neighbour enumeration still has to visit its entries.
The advantage grows with scale. For a graph path on vertices, , so there are undirected neighbour entries and descriptors, versus full adjacency matrix entries. Such a family is a sparse graph with . For a complete graph, , so the undirected neighbour entries already number : the adjacency list advantage in growth rate disappears. Choose by the workload: following existing edges favours adjacency lists; many arbitrary pair-membership queries can favour a full adjacency matrix. The representation organizes the same graph for different questions.
For Boolean matrices, replace numerical addition by logical disjunction and multiplication by logical conjunction. Applied to adjacency matrices, the product records a walk formed by following one segment represented by the first matrix and one represented by the second. For an adjacency matrix on vertices, start from . Repeated squaring then computes reflexive transitive closure once the exponent reaches : the identity entries pad shorter walks, and every reachable pair has a simple path of length at most .
Closed walk Created 2026-10-06 Updated 2026-10-14
A closed walk is a walk with equal endpoint vertices, . Under our convention this includes the zero-length walk ; returning after traversing at least one edge requires . Closure imposes no other restriction on repeated vertices or edges. In a directed graph, a closed directed walk must also follow every directed edge in its permitted direction.[ref]
Figure 1.
Returning to : backtracking closed walk, closed trail with a repeated internal vertex, and graph cycle
. Details.
In the shared simple graph, is a length-two closed walk that immediately backtracks along . It is not a trail, since is used twice, and it is not a graph cycle. The length-six closed walk is a trail, since its six edges are distinct, but is not a graph cycle: it returns to midway through the journey. The length-three closed walk is a graph cycle, with all vertices distinct apart from the required endpoint repetition. In a simple graph that is an undirected graph, a graph cycle has length at least three; the two-step backtrack is excluded.[ref]
A positive-length closed walk therefore need not reveal a graph cycle: even a tree permits an out-and-back journey on an edge. A positive-length closed trail in a simple graph does contain a graph cycle. For a proof outline, choose a shortest positive-length consecutive portion of the trail whose endpoint vertices coincide. It cannot repeat an internal vertex, since that would give a shorter such portion; it cannot have length one or two because self-loops and repeated edges are excluded. It is consequently a graph cycle. Cutting it out leaves another closed trail, possibly of length zero, so repetition partitions the original edges into graph cycles. In our six-step example these are the two triangles in a graph. A closed trail using every edge would be an Euler circuit; here is omitted.
Counting return journeys makes closed walks useful even when they repeat edges. For a finite simple graph with adjacency matrix , the walk count from powers of an adjacency matrix gives length- walks from to , for every nonnegative integer . A proof outline is that matrix multiplication appends one allowed step, summing over the previous endpoint; is the identity matrix, recording the unique zero-length walk at each vertex. Consequently
The trace counts closed walks with a specified starting vertex and traversal order, not distinct graph cycles. These formulas use adjacency entries, not arbitrary travel costs in a weighted graph.[ref]
In our example, : the five length-two closed walks are , , , , and . Also , going round either triangle in a graph in either direction, and : each of the two triangles in a graph supplies three choices of starting vertex and two directions. These exact counts for the constructed graph illustrate why return counts and graph cycle counts differ.
A closed walk naturally models a delivery or inspection journey that returns to its depot. Repeated vertices let it combine several excursions; repeated edges let it serve a dead end and return. For an Euclidean travelling salesman tour, one can first construct a closed walk visiting all locations and then use the triangle inequality to shortcut repeated visits without increasing total length. That argument assumes direct travel between the retained locations is permitted, as in a complete graph weighted by Euclidean distance; an arbitrary road network need not contain those shortcut edges.
With one orthonormal site orbital per cube vertex, common site energy , and coupling along every edge, the one-electron Hamiltonian is , where is the cube adjacency matrix. Its eigenvalues are with multiplicities .
One proof labels each vertex by three signs. The adjacency operator flips one sign at a time, so a product of coordinate signs is an eigenfunction of with eigenvalue . There are such products. For , eight electrons fill the lowest four spatial molecular orbitals, yielding total one-electron energy .
Degree matrix 2026-10-14
The degree matrix is the diagonal matrix whose th diagonal entry is the degree of a vertex . For a finite simple graph, , where is its adjacency matrix. For a Weighted graph Laplacian, use the sum of incident edge weights instead of the number of incident edges.
Eigenvector centrality 2026-10-20
Eigenvector centrality assigns nonnegative vertex scores proportional to the sum of neighbouring scores: . It uses a nonnegative eigenvector of the adjacency matrix for its largest positive eigenvalue. State the normalization, such as Euclidean norm one. For a three-leaf star graph, hub and leaf scores have ratio .
Graph Created 2026-09-24 Updated 2026-10-18
Figure 1.
Two drawings of the same six-vertex graph and its adjacency matrix
. Details.
A graph describes objects, called vertices, and pairwise connections, called edges. Its vertex set tells us what the objects are; records their connections. The basic abstraction retains graph adjacency while discarding positions, angles and Euclidean distances: moving the dots in a drawing changes none of the edges. A crossing of two drawn lines is not an extra vertex unless explicitly designated as one. Even the labels can change: a graph isomorphism is a relabelling that preserves graph adjacency in both directions.[ref]
This makes graphs useful when the question concerns possible connections rather than physical shape. For example, model locations by vertices and direct links by edges; a graph path answers whether one location can reach another. Alternatively, let vertices be activities and edges represent conflicts: a graph coloring then assigns compatible time slots. These are mathematical models, so one must decide which pairwise relationship an edge means before applying graph theory.[ref]
Our running simple graph has
where abbreviates the unordered pair . It consists of two triangles in a graph, and , joined by . The two drawings above have identical graph adjacency, even though their apparent lengths differ. What counts is that and are adjacent, whereas and are not.
Route questions require precise vocabulary. A walk is a sequence of consecutive adjacent vertices, permitting repetitions; its length counts traversed edges. A trail is a walk that repeats no edge; a graph path repeats no vertex. For a multigraph, the walk must also specify which parallel edge each step uses. For instance, is a length-five walk but not a trail, since it uses twice. The length-three graph path is a shortest route: crossing between the two triangles in a graph requires , with at least one edge before it and one after it. Thus in graph distance, regardless of the drawing.[ref]
An Eulerian trail uses every edge exactly once, allowing repeated vertices; a Hamiltonian path visits every vertex exactly once, without needing every edge. Here is an Eulerian trail of length seven, whereas is a Hamiltonian path of length five. The first repeats ; the second omits . Calling an Eulerian trail an "Eulerian path" must not be taken to impose our graph path convention.[ref]
The classic historical example is Euler's Königsberg bridge problem: represent the four land regions by vertices and the seven bridges by distinct edges, giving a multigraph. Their degrees of vertices are . In a trail using every edge, arrivals and departures pair at every internal vertex, so at most the two endpoints can have odd vertex degree. Four odd degrees of vertices therefore rule out such a route. This early foundational example of graph theory needs neither bridge lengths nor a geographical map. Euler's paper is conventionally associated with 1736, the volume's nominal year; the Euler Archive records its writing in 1735 and publication in 1741.[ref][ref]
Assign a real value to each vertex. The Graph Laplacian quadratic form measures disagreement across edges:
This makes the Graph Laplacian a positive semidefinite matrix. The energy is small when neighbours have similar values, even if distant vertices have very different values; it depends on connections rather than where the graph is drawn. In the three-vertex path graph, take . Then
and the two edges contribute and .
Figure 1.
Edge disagreement and eigenvectors of the three-vertex path Laplacian
. Details.
For a short proof, expand . Each edge contributes through the degree matrix and through the adjacency matrix, yielding . The sum over unordered edges has no factor ; a sum over all ordered pairs does:
Equivalently, let be an oriented incidence matrix, with one row per edge. Then records endpoint differences and , independently of the chosen orientations. This translates a local comparison into a global quadratic form and makes its nonnegativity visible.
Laplacian matrix Created 2026-10-14 Updated 2026-10-20
The Graph Laplacian converts local differences along edges into a linear map. Throughout this section, is a finite undirected graph with no self-loops or repeated edges, and each edge has weight one. In a fixed order of vertices, let be the adjacency matrix and the degree matrix. The combinatorial Graph Laplacian is
Thus the value at a vertex is compared with its neighbours. Every row sums to zero, so : a constant vector produces no differences. This definition and the associated Graph Laplacian quadratic form are developed in Spielman's authored survey.[ref]
For the three-vertex path graph , the vertex degrees are , and in that order
Direct multiplication gives three eigenvectors and their eigenvalues:
The constant eigenvector has eigenvalue zero; the other two describe progressively stronger neighbour disagreement. Dividing these eigenvectors by , respectively, gives an orthonormal basis. The four-vertex cycle graph is already worked out under circulant matrix, where Fourier diagonalization of a circulant matrix gives its eigenvalues.
Every formula here uses without degree normalization. For comparison, Chung's treatment uses the degree-scaled matrix , with a convention for isolated vertices; its eigenvalues must not be substituted into the examples here.[ref]
Neighbour enumeration 2026-10-14
Neighbour enumeration reports the neighbours of a specified vertex. For a simple graph, scan its adjacency list and report each entry. With constant-time list access and work per entry, a list of length needs time in Big O notation, conventionally written for nonempty lists. Use vertex degree for an undirected graph and outdegree for a directed graph. Obtaining the list reference can take constant time; consuming it requires visiting every entry.[ref]
In our undirected example, enumerating 's neighbours reads : three entries. Scanning row of the full adjacency matrix reads six entries, , to produce the same answer. In the directed variant, enumerating 's outgoing neighbours reads no neighbour entries, but still needs constant work to locate and recognize its empty list. For a multigraph, scanning lists enumerates incident edges with multiplicity; reporting only distinct neighbours additionally requires removing repetitions.
For a short time complexity argument, each reported entry requires at least one output operation, and one scan suffices. Across all vertices, the undirected entry count is by the handshaking lemma; the directed count is . A graph search that processes each vertex once and scans each of its entries once therefore does structural work, provided its visited-state access and FIFO queue or stack operations also have the required constant-time costs. With a full adjacency matrix, scanning every row instead inspects entries. This is how the representation enters the analysis of breadth-first search and depth-first search.
To establish strong NP-completeness, use an explicit adjacency matrix encoding for a finite simple graph, with enough length information to recover its number of vertices. Let be the canonical binary numeral system representation of the nonnegative integer . Define
and, using the unary numeral system for ,
The surrounding pairing syntax delimits the two components, so the empty unary field can encode if zero is included in the convention for natural numbers. Malformed descriptions are excluded from both formal languages.
Fix a unary no-instance , for example one isolated vertex with requested size . The polynomial-time many-one reduction is
Map malformed inputs to too. When , only the numerical representation changes, so the existence of a -clique is unchanged. When , the original instance is false, since a subset of vertices cannot be larger than the whole vertex set; is false as required.
The important size bound is in the branch that writes . The original explicit graph description already has length at least , so the output has polynomial length and can be written in polynomial time. If a huge binary numeral system value is supplied, compare it with using its digit length and, when needed, a digit comparison; do not first allocate or print symbols. Merely replacing an unrestricted binary by would not be a valid polynomial-time reduction.
Thus . The unary version is in NP by the same clique complexity certificate verification, and is NP-hard by this polynomial-time many-one reduction and part (e). Therefore
This conclusion uses the conventional explicit graph encoding; a succinct circuit description of a graph would be a different input representation and a different problem.
Directed reachability is NL-complete under logspace many-one reductions. For membership, let be the number of vertices. Store a current vertex, initially , and a counter initially zero. Accept immediately if the current vertex is . Otherwise guess a next vertex, verify by scanning the input that the appropriate directed edge exists, move there and increment the counter. Reject a branch that has made steps without reaching .
Whenever a directed walk reaches , removing closed portions between repeated vertices produces a path in a graph with at most edges. Thus this bound preserves all yes-instances. The current and guessed vertices and the counter use bits, while adjacency checks only need repeated read-only input scans. All branches halt, so directed reachability belongs to NL.
For hardness, let and fix a Nondeterministic Turing machine accepting in work space. On input , construct its configuration graph . A vertex is a possible Turing machine configuration within the fixed work-space bound. Put a directed edge exactly when one legal transition of on changes into . Take the initial Turing machine configuration as source, and add a fresh target with an incoming edge from every accepting Turing machine configuration. Then
There are only a polynomial number of Turing machine configurations, by the count used in part (c). More importantly, their encodings have length . A logspace transducer can enumerate candidate encodings and pairs of candidate encodings with bits of counters. For each pair, it checks the finite transition rule, the scanned input symbol and the local work-tape change using work space. It emits the corresponding adjacency matrix entry or edge-list record. Invalid candidate encodings may be discarded or represented by isolated vertices.
The configuration graph is thus output by a logspace transducer, rather than stored in its work tapes. This supplies the required logspace many-one reduction from every and proves NL-completeness.
A transition relation requires an explicit interpretation of the Boolean variables as current and next state bits. Take the four states . Encode the current state by and the next state by , and define
The extra current bit is deliberately unused by the Boolean formula. A four-state transition system normally needs four bits to describe a pair of states; a Boolean formula using only three of them simply describes a transition relation independent of the fourth bit.
When , the condition is , so the permitted next states are and . When , the condition is , so the permitted next states are . The resulting adjacency matrix, with rows and columns both ordered , is
The directed graph below plots all ten directed edges, including the three self-loops. No arrow enters , but it is a valid state with two outgoing arrows. Every state has a successor. As permitted, no initial states are distinguished.
Figure 1.
Four-state transition system with current bits (u, x), next bits (y, z), and relation y or (x and z)
. Details.
Enumerate the vertices as and introduce a Boolean variable for each ordered pair of vertices. Its intended meaning is that a proposed graph automorphism sends to . Build four groups of Boolean clauses.
First require exactly one image for each vertex:
Next require that distinct vertices have distinct images:
Together and specify an injective function . Since is finite, this function is a bijection; a separate surjectivity condition is unnecessary.
Write when and otherwise. Prohibit every pair of images that would change adjacency:
Checking both possible mismatches preserves both edges and nonedges. Finally require a moved vertex:
The desired propositional formula is
If a Boolean valuation satisfies , selects a unique image for every vertex, makes the resulting function a bijection, preserves adjacency in both directions, and makes this graph automorphism different from the identity function. Conversely, given such a graph automorphism , set true exactly when . Each of is then satisfied.
There are Boolean variables, image and injectivity Boolean clauses, and at most adjacency Boolean clauses. With the graph stored by its adjacency matrix, testing a mismatch takes constant time. Thus the construction has polynomial time and output length with binary-indexed variable names. For , interpret the empty logical disjunction as false; for , and conflict. These cases correctly have no nonidentity graph automorphism.
Use vertices . Reading each symmetric off-diagonal pair once gives the edge set
Here abbreviates the undirected edge . The diagram displays these seven edges and no loops. The displayed square matrix is an adjacency matrix in the usual terminology: its two indices both label vertices. A vertex-edge incidence matrix would instead have one index for vertices and one for edges. This explains how the source's node-node terminology is being read.
Figure 1.
The graph and its maximum-weight forest, including the isolated fourth vertex
. Original drawing. The left panel shows all seven edges. The right panel shows only the three edges selected for the maximum-weight forest, with their weights; vertex four remains isolated. Details.
The supplied adjacency matrix describes a four-vertex cycle graph, with every vertex degree equal to two. Degree-preserving edge rewiring is random, so it does not determine one unique labelled output adjacency matrix. For example, replace edges and by and , retaining and . This valid switch gives, in order ,
Each row still sums to two. Under the simple graph convention, all allowed outputs have the same unlabelled four-cycle topology: there are three possible labelled four-cycles. A rejected switch or later return can also leave the original adjacency matrix.
It is not a scale-free network. Its degree distribution is concentrated entirely at degree two, with no power-law tail; degree-preserving edge rewiring cannot change that.
For an undirected graph with adjacency matrix , degrees of vertices and edges, network modularity is
Each undirected edge contributes twice to the double sum, explaining the denominator . Include the terms with : even though the observed graph has no self-loops, the null-model contribution on the diagonal is part of this definition.
An independent implementation forms the modularity matrix and sums its within-community blocks. Initializing the best value to negative infinity also handles a candidate collection whose scores are all negative:
def modularity(adjacency,communities):
    a=np.asarray(adjacency);degrees=a.sum(axis=1);twom=degrees.sum()
    if twom==0:raise ValueError('positive edge count required')
    B=a-np.outer(degrees,degrees)/twom
    return sum(B[np.ix_(group,group)].sum() for group in communities)/twom

best_score = -np.inf
best_partition = None
for candidate in community_partitions:
    value = modularity(adjacency_matrix, candidate)
    if value > best_score:
        best_score, best_partition = value, candidate
print(best_partition, best_score)
The best partition is , with . There are seven edges, and each selected community has three internal edges and total degree seven, so independently
The supplied candidates include the optimum, but do not exhaust even the balanced two-community set partitions: there are of those, rather than six. To substantiate a best partition among all community counts, the following short recursion enumerates all 203 unlabeled set partitions of the six vertices:
def partitions(items):
    if not items:
        yield [];return
    first,*rest=items
    for part in partitions(rest):
        yield [[first]]+[g.copy() for g in part]
        for j in range(len(part)):
            new=[g.copy() for g in part];new[j]=[first]+new[j];yield new

candidates = list(partitions(list(range(len(adjacency_matrix)))))
best_partition = max(candidates, key=lambda p: modularity(adjacency_matrix, p))
print(len(candidates), best_partition, modularity(adjacency_matrix, best_partition))
This exhaustive calculation returns the same two triangles and the same network modularity. Enumerating every set partition becomes impractical rapidly as the number of vertices increases, but is small enough here to verify the global optimum.
Factor the characteristic polynomial as . The eigenvalues, with algebraic multiplicity, are therefore
The adjacency matrix describes a star graph with node 1 as the hub. For the positive leading eigenvalue , write the hub component as . The leaf equations , for , give equal leaf components . The hub equation is , which is consistent precisely because . Thus an eigenvector is .
Normalizing its Euclidean norm to one gives the eigenvector centrality
Numerically this is . It satisfies both and . If “normalized” instead means maximum component one, use ; if it means components summing to one, divide by . The hub-to-leaf ratio is invariant under these conventions. The negative leading-magnitude eigenvalue also has an eigenvector, but its mixed signs do not define nonnegative eigenvector centrality.
Let be a finite undirected -regular graph on vertices, with adjacency matrix and normalized random walk matrix . Define edge expansion and normalized conductance by
An expander family has orders tending to infinity, uniformly bounded maximum degree, and a uniform positive lower bound on . For a regular graph the constant vector is an eigenvector of with eigenvalue one. Write its eigenvalues as , and let . This spectral gap measures the energetic cost of departing from a constant function.
For every mean-zero vector , the spectral theorem and the graph's energy identity give
Apply this to . Its norm squared is and its energy is . Therefore
Thus a uniform spectral gap gives uniform edge expansion when is fixed. This also bounds exterior vertex expansion: each exterior vertex accounts for at most boundary edges, so .
For the converse, take a mean-zero eigenvector for and choose its sign so that its positive support has at most vertices. Put , which is nonzero. Truncation decreases energy in the following precise sense: for any two real numbers ,
Summing over edges yields . For the threshold sets , every nonempty set lies in that small positive support. Integrating its boundary count gives the layer-cake identity
The Cauchy-Schwarz inequality bounds the left side by
because the first sum is at most and the second at most . Cancelling proves the Cheeger inequality in both directions:
Hence bounded-degree regular families have uniform edge expansion exactly when their second-largest normalized eigenvalue stays uniformly below one.
Absolute eigenvalues give additional information. Put . Centering the indicators of and applying the operator-norm bound on the mean-zero subspace proves the expander mixing lemma:
Here , so internal edges are counted as oriented incidences. A small makes edge counts resemble uniformly distributed edges. It also gives rapid random walk mixing: starting at a vertex, contracts the mean-zero component of its point mass by at most in Euclidean norm; Cauchy-Schwarz inequality then gives total variation distance at most from the uniform distribution. A bipartite graph has eigenvalue and its non-lazy walk alternates sides, even if it has good edge expansion. The lazy walk has nonconstant eigenvalues between zero and , resolving this periodicity. It is important to distinguish the gap controlling cuts from the absolute bound controlling non-lazy mixing.
Here is a fully specified deterministic construction of an infinite family. Its degree is large but fixed. Set
Choose the lexicographically first ordered list satisfying
This finite deterministic search terminates. To prove existence, choose the list uniformly and independently. For each nonzero , its signs are independent unbiased signs; the exponential-moment estimate and Markov inequality give an exceptional probability at most . A union bound gives total failure probability at most
Thus at least one qualifying list exists. Fix it once and for all.
Let be the Cayley graph on whose th neighbor of is . It is an undirected -regular port-labeled graph, allowing repeated edges and loops in this intermediate construction. Its characters form an orthogonal eigenbasis, with the displayed averages as normalized eigenvalues. Therefore . Each loop counts as one transition port; degrees here mean row sums of the adjacency matrix.
We next define the zig-zag product and prove the bound used for iteration. A port labeling of a -regular undirected graph gives an involution , recording the endpoint and reverse port. If a -regular graph has vertex set , the product has vertices . For each ordered pair of small-graph ports, move from to in , follow the big edge , and move from to in . The endpoint is ; reversing the steps reverses the two small-graph port labels. The product is undirected, has vertices, and has degree .
Write and let be the permutation matrix of . The normalized product operator is . For a mean-zero unit vector, decompose into its cloud-constant part and its cloud-orthogonal part. Then , , and . The compression of to cloud-constant vectors is exactly , so . Expanding the quadratic form and applying Cauchy-Schwarz inequality gives
The operator is symmetric, so its mean-zero operator norm is bounded by this same quantity. No unproved product spectral estimate is needed.
Start with the loop-inclusive complete graph on vertices, whose normalized matrix is and whose nonconstant eigenvalues are all zero. Given a -regular , its two-step graph has degree and normalized operator . Label a two-step edge by its ordered pair of ports; reversal reverses the path and its reverse ports. These labels are the vertex set of the fixed graph . Define
It has degree , and its number of vertices is , hence . By the proved bound,
Starting from zero, induction gives , since . The cut-energy argument therefore gives multiplicity-counted edge expansion at least for every .
To obtain ordinary simple graphs, delete loops and merge parallel edges. The maximum degree is at most , and any one unordered vertex pair had multiplicity at most . Thus every cut retains at least of its multiplicity-counted boundary, giving
These simple graphs form an expander family. Every choice is deterministic: the finite base search is fixed independently of , and the recursive edge rules determine all subsequent adjacency lists. Once that base is fixed, adjacency lists can be generated successively using the previous lists, with a constant amount of work per output edge. This is squaring and zig-zag iteration yields bounded-degree expanders. The spectral argument supplies the uniform expansion guarantee and explains why squaring improves the eigenvalues while the product restores a constant degree.