Graph Structures and AlgorithmsIntroductionGraphs provide a general model for representing relationships among objects. A computer network, road system, social network, prerequisite structure, recommendation system, and workflow can all be represented as graphs. Unlike linear structures such as arrays, stacks, and queues, graphs allow an element to be connected to any number of other elements. A graph consists of vertices (also called nodes) and edges (also called links or arcs). Algorithms on graphs answer questions such as: - Which objects are reachable from a starting object?
- Are all locations connected?
- What is the least-cost route between two locations?
- Can tasks be arranged in a valid dependency order?
- Does a network contain a cycle?
- What is the cheapest set of links connecting all locations?
Graph algorithms are therefore central to software engineering, cybersecurity, databases, artificial intelligence, geographic information systems, and operations research. Learning ObjectivesBy the end of this chapter, a student should be able to: - Define and classify directed, undirected, weighted, and labeled graphs.
- Select and implement adjacency-list and adjacency-matrix representations.
- Apply breadth-first search and depth-first search.
- Determine reachability, connectivity, and cycle existence.
- Compute shortest paths using appropriate algorithms.
- Construct minimum spanning trees.
- Produce a topological ordering for a directed acyclic graph.
- Evaluate algorithmic complexity and practical limitations.
1. Fundamental Graph ConceptsA graph is commonly written as G = (V, E), where V is the set of vertices and E is the set of edges. Let n = |V| denote the number of vertices and m = |E| the number of edges. In an undirected graph, an edge connects two vertices symmetrically. If an edge joins A and B, movement is possible in both directions. In a directed graph, an edge has an origin and destination. The edge A → B does not imply that B → A exists. A weighted graph associates a numerical value with each edge. The value may represent distance, cost, time, bandwidth, risk, or energy. A labeled graph assigns descriptive information to vertices or edges, such as a city name, road type, account category, or relationship type. Graphs may be directed and weighted simultaneously. Important terminology includes: - Adjacent vertices: vertices joined by an edge.
- Incident edge: an edge connected to a vertex.
- Degree: number of incident edges in an undirected graph.
- In-degree: number of incoming edges to a vertex.
- Out-degree: number of outgoing edges from a vertex.
- Path: a sequence of vertices connected by edges.
- Simple path: a path that does not repeat vertices.
- Cycle: a closed path that begins and ends at the same vertex.
- Connected graph: an undirected graph in which every pair of vertices has a path between them.
- Strongly connected directed graph: every vertex can reach every other vertex following edge directions.
- Subgraph: a graph formed from subsets of vertices and edges of another graph.
For an undirected graph, the sum of all vertex degrees equals twice the number of edges: ∑ degree(v) = 2m This is the handshaking theorem. Each edge contributes one incidence to each endpoint. For a directed graph, the sum of in-degrees equals the sum of out-degrees, and both equal the number of directed edges: ∑ in-degree(v) = ∑ out-degree(v) = m A graph with an edge from every vertex to every other distinct vertex is a complete graph. An undirected complete graph with n vertices has: m = n(n − 1) / 2 This formula applies only to simple undirected graphs, meaning that loops and duplicate edges are not permitted. 2. Graph RepresentationsThe representation should reflect the graph’s density, operations, and memory constraints. 2.1 Adjacency MatrixAn adjacency matrix is an n × n table. For an unweighted graph, entry A[i][j] is 1 if an edge from vertex i to vertex j exists and 0 otherwise. For a weighted graph, the entry stores the edge weight; a special value such as infinity represents no edge. For an undirected graph, the matrix is symmetric: A[i][j] = A[j][i]. A matrix uses O(n2) memory, regardless of the number of edges. Testing whether an edge exists takes O(1) time, while listing all neighbors of one vertex takes O(n). Matrices are effective for dense graphs and algorithms that repeatedly test arbitrary pairs of vertices. They are inefficient for sparse graphs because most entries may contain no edge. 2.2 Adjacency ListAn adjacency list stores, for each vertex, a collection of its neighbors. A weighted list stores pairs such as (neighbor, weight). For a directed graph, only outgoing neighbors are normally stored; an additional reverse list can be maintained when incoming-neighbor queries are common. An adjacency list uses O(n + m) memory. Iterating over the neighbors of vertex v takes O(degree(v)) time. Edge-existence testing is typically O(degree(v)) with an unsorted list, although hashing can improve expected performance. Adjacency lists are generally preferred for sparse graphs and for traversal algorithms. 2.3 Edge ListAn edge list stores edges explicitly, for example (A, B, 7). It is simple and compact, especially when the main operation is processing every edge. Kruskal’s minimum-spanning-tree algorithm and Bellman–Ford shortest paths commonly use edge lists. | Representation | Space | Edge test | Best use |
|---|
| Adjacency matrix | O(n²) | O(1) | Dense graphs, pair queries | | Adjacency list | O(n+m) | Depends on list | Sparse graphs, traversal | | Edge list | O(m) | O(m) | Edge-oriented processing |
3. Graph TraversalTraversal systematically visits vertices while avoiding repeated work. A traversal normally maintains a visited set. Without it, a cyclic graph can cause infinite repetition. 3.1 Breadth-First SearchBreadth-first search (BFS) explores vertices in layers according to their number of edges from the starting vertex. It uses a queue. Algorithm: BFS - Mark the start vertex visited and enqueue it.
- While the queue is not empty, remove its front vertex u.
- For each unvisited neighbor v of u, mark v visited, record u as its predecessor, and enqueue v.
- Continue until the queue is empty or the target is found.
With an adjacency list, BFS runs in O(n + m) time because every vertex and edge is processed at most a constant number of times. Its space complexity is O(n), excluding the graph itself. In an unweighted graph, BFS produces shortest paths measured by number of edges. If the predecessor of each vertex is recorded, the path can be reconstructed by following predecessors backward from the target. Worked example. Suppose the edges are A–B, A–C, B–D, C–E, and D–F. BFS from A visits A first, then B and C, then D and E, and finally F. The distance from A to F is 3 edges. A predecessor chain is F ← D ← B ← A. 3.2 Depth-First SearchDepth-first search (DFS) follows one path as far as possible before backtracking. It can be implemented recursively or with an explicit stack. Algorithm: DFS - Mark the current vertex visited.
- For each unvisited neighbor, recursively perform DFS on that neighbor.
- Return when all neighbors have been explored.
DFS also runs in O(n + m) time with adjacency lists and O(n) auxiliary space. It is useful for connected components, cycle detection, topological sorting, articulation analysis, and maze exploration. The order produced by DFS depends on the order in which neighbors are stored. Therefore, traversal order is not necessarily unique. 4. Connectivity and Cycle Detection4.1 Connected ComponentsFor an undirected graph, run DFS or BFS from every unvisited vertex. Each search identifies one connected component. The total time is O(n + m). A graph is connected if exactly one component is found. For directed graphs, ordinary reachability is directional. A graph is strongly connected if every vertex can reach every other vertex. Strongly connected components can be found using algorithms such as Kosaraju’s or Tarjan’s algorithm, both of which run in O(n + m) time. 4.2 Cycle Detection in Undirected GraphsDuring DFS, an edge from the current vertex to an already visited vertex may indicate a cycle. However, the edge leading back to the current vertex’s parent must be ignored because undirected edges appear in both adjacency lists. An alternative is a disjoint-set union structure. Process each edge (u, v): if u and v are already in the same set, the edge creates a cycle; otherwise, union their sets. With path compression and union by rank, a sequence of operations has near-constant amortized cost, commonly expressed as O(m α(n)), where α is the very slowly growing inverse Ackermann function. 4.3 Cycle Detection in Directed GraphsDFS detects a directed cycle by tracking three states: - unvisited,
- currently being explored,
- completely explored.
An edge to a currently explored ancestor, called a back edge, proves the existence of a directed cycle. This method runs in O(n + m). 5. Shortest-Path AlgorithmsThe shortest-path problem seeks a path with minimum total weight. For a path containing edges with weights w₁, w₂, …, wₖ, its total cost is: cost(path) = w₁ + w₂ + ⋯ + wₖ This additive model assumes that path costs can be summed and that the objective is minimization. 5.1 Choosing an Algorithm| Conditions | Suitable method |
|---|
| Unweighted graph | BFS | | Nonnegative edge weights, one source | Dijkstra’s algorithm | | Negative edges, no negative cycle | Bellman–Ford | | All pairs, small or moderate n | Floyd–Warshall |
5.2 Dijkstra’s AlgorithmDijkstra’s algorithm maintains the best currently known distance from a source s. Initially, distance(s) = 0 and every other distance is infinity. Repeatedly select the unprocessed vertex with the smallest tentative distance and relax its outgoing edges. For an edge u → v with weight w(u, v), relaxation applies: d[v] = min(d[v], d[u] + w(u, v)) Here d[x] is the current best distance from the source to x. If a priority queue implemented with a binary heap is used, the complexity is O((n + m) log n). With an adjacency matrix and simple selection, it is O(n²). Dijkstra is correct when every edge weight is nonnegative. It must not be used with negative edge weights, even if no negative cycle exists. Worked example. Consider edges A → B (4), A → C (1), C → B (2), B → D (1), and C → D (5). Starting at A: - Initially: d(A)=0, d(B)=4, d(C)=1, d(D)=∞.
- Select C: update B to 3 and D to 6.
- Select B: update D to 4.
- Select D: no improvement.
The shortest distance from A to D is 4, through A → C → B → D. 5.3 Bellman–Ford AlgorithmBellman–Ford relaxes every edge repeatedly, up to n − 1 times. If any edge can still be relaxed after that, a reachable negative-weight cycle exists. Its time complexity is O(nm). The algorithm is slower than Dijkstra but supports negative edges. A negative cycle makes the shortest-path problem undefined for vertices reachable from that cycle because a path can be made arbitrarily cheap by circling repeatedly. 5.4 Floyd–Warshall AlgorithmFloyd–Warshall computes shortest paths between every pair of vertices. It progressively permits intermediate vertices. Its recurrence is: d[i][j] = min(d[i][j], d[i][k] + d[k][j]) At stage k, d[i][j] is the best distance from i to j using only permitted intermediate vertices among the first k vertices. The time complexity is O(n³) and the usual space complexity is O(n²). Negative edges are allowed, but a negative cycle can be detected when some diagonal entry d[i][i] becomes negative. 6. Minimum Spanning TreesA spanning tree of a connected undirected graph includes every vertex, contains no cycle, and has exactly n − 1 edges. A minimum spanning tree (MST) is a spanning tree with minimum total edge weight. MST algorithms apply to connected, undirected, weighted graphs. They do not solve the shortest route from one source to every destination; an MST minimizes the total cost of selected network links, not each individual route. 6.1 Kruskal’s AlgorithmKruskal’s algorithm sorts edges by nondecreasing weight. It repeatedly adds the next edge if that edge connects two different components. A disjoint-set structure efficiently tests whether an edge would create a cycle. With sorting, the complexity is O(m log m), usually written O(m log n) for simple graphs because m ≤ n². 6.2 Prim’s AlgorithmPrim’s algorithm begins with any vertex and repeatedly adds the cheapest edge connecting the growing tree to a vertex outside it. With an adjacency list and binary heap, its complexity is O((n + m) log n). Worked example. Suppose a network has edges A–B=1, A–C=4, B–C=2, B–D=5, C–D=3. Kruskal selects A–B (1), B–C (2), and C–D (3), producing an MST of total weight 6. The edge A–C is rejected because it would create a cycle, and B–D is unnecessary. 7. Topological OrderingA topological ordering is a linear ordering of vertices in a directed acyclic graph (DAG) such that for every edge u → v, u appears before v. It represents prerequisite or dependency relationships. A topological ordering exists if and only if the directed graph has no cycle. 7.1 Kahn’s Algorithm- Compute the in-degree of every vertex.
- Place all zero-in-degree vertices in a queue.
- Remove one such vertex and append it to the ordering.
- Decrease the in-degree of its outgoing neighbors.
- Add any neighbor whose in-degree becomes zero.
- If fewer than n vertices are output, the graph contains a cycle.
The complexity is O(n + m). If several zero-in-degree vertices exist, more than one valid ordering may be possible. 7.2 DFS-Based OrderingDFS can produce a topological order by placing each vertex on a stack when its exploration finishes, then reversing the finish order. A recursion-stack check is required to reject cycles. Example. For prerequisites A → C, B → C, and C → D, valid orders include A, B, C, D and B, A, C, D. The order A, C, B, D is invalid because B must precede C. 8. A Practical Application: Emergency-Routing NetworkThe following is an illustrative case study. BackgroundA city emergency service operates stations, hospitals, and major intersections connected by roads. Each road has a travel-time estimate. Some roads may be temporarily unavailable, and dispatchers need both fast routing and resilient network design. ProblemThe service must answer three questions: - What is the fastest route from a station to an incident?
- Can every important location still be reached if a road is unavailable?
- What minimum set of communication links connects all stations for backup coordination?
AnalysisIntersections and facilities are represented as vertices. Roads are directed if traffic restrictions make travel one-way; otherwise they are represented as undirected edges. Travel times are nonnegative weights. Names, road classes, and emergency restrictions are labels. An adjacency list is appropriate because a city map is usually sparse relative to the number of possible pairs of locations. BFS can provide minimum-hop routes when all roads are treated equally. Dijkstra’s algorithm provides minimum travel-time routes when all travel-time weights are nonnegative. DFS or BFS can identify disconnected areas after a road failure. Prim’s or Kruskal’s algorithm can design a low-cost backup communications network. Approach and SolutionThe system maintains: - an adjacency list for current roads;
- a priority queue for Dijkstra’s algorithm;
- predecessor records for reconstructing routes;
- a disjoint-set structure for rapid connectivity checks during network design;
- edge and vertex labels for restrictions and operational categories.
When a road is closed, the system removes or disables that edge and recomputes affected routes. If road closures create separate components, dispatchers are warned that some locations are unreachable. For planned infrastructure, an MST minimizes total installation cost, while shortest-path calculations determine operational travel routes. OutcomeThe design distinguishes two objectives that are often confused: shortest paths minimize the cost of individual journeys, whereas an MST minimizes the total cost of connecting the entire network. Using the correct algorithm improves both response time and infrastructure planning. Learning Points- Data representation affects memory use and performance.
- Edge direction must reflect actual movement rules.
- Nonnegative travel times justify Dijkstra’s algorithm.
- Connectivity analysis is essential after failures.
- A minimum spanning tree is not a replacement for route planning.
9. Implementation and Engineering ConsiderationsInput ValidationA graph implementation should validate vertex identifiers, reject malformed edges, define whether parallel edges are permitted, and state how self-loops are treated. For weighted graphs, units and allowable ranges must be documented. Numerical IssuesWeights may be integers, floating-point values, or application-specific quantities. Infinity must be represented safely so that adding a finite weight to infinity does not overflow. Floating-point comparisons may require a documented tolerance when weights are computed rather than exact. ScalabilityFor large sparse graphs, adjacency lists and priority queues are normally preferable. For dense graphs or repeated pair queries, matrices may be more suitable. External-memory and distributed graph systems may partition vertices and edges, but partition boundaries can create communication overhead. Correctness and TestingTests should include empty graphs, isolated vertices, disconnected components, duplicate edges, self-loops, directed cycles, negative edges, equal weights, and unreachable destinations. For shortest paths, compare predecessor chains and total weights, not only final distances. For MSTs, verify that the output has n − 1 edges, is connected, and contains no cycle. Ethical and Governance IssuesGraph algorithms can influence emergency dispatch, credit relationships, employment networks, and social recommendations. Graph data may expose personal relationships or sensitive locations. Systems should apply access controls, minimize unnecessary data collection, document decision criteria, and audit outcomes for unfair or discriminatory effects. An algorithmically shortest route may not be socially appropriate if it directs traffic through unsafe neighborhoods or violates access restrictions. Technical correctness does not remove the need for human oversight. 10. Contemporary DevelopmentsModern applications use graph databases, knowledge graphs, graph neural networks, and streaming graph analytics. Graph databases store relationships as first-class records and support queries involving paths and neighborhood patterns. Knowledge graphs connect entities with labeled, often directed relationships. Graph neural networks learn from both vertex attributes and graph structure. These technologies do not replace fundamental algorithms. Traversal, connectivity, shortest paths, and cycle detection remain essential for interpreting data, designing query engines, validating models, and explaining results. In AI systems, graph-based explanations can help identify which relationships contributed to a prediction, although explanations must still be evaluated for completeness and fairness. Best-Practice Checklist- Define whether edges are directed or undirected.
- Specify the meaning and units of weights.
- Choose adjacency lists for most sparse graphs.
- Use BFS for unweighted shortest paths.
- Use Dijkstra only when edge weights are nonnegative.
- Use Bellman–Ford when negative edges may occur.
- Distinguish shortest-path problems from MST problems.
- Detect cycles before attempting topological ordering.
- Record predecessors when paths must be reconstructed.
- Test disconnected, cyclic, empty, and malformed inputs.
- Protect sensitive graph data and audit high-impact decisions.
Chapter SummaryGraphs model relationships using vertices and edges. They may be directed, undirected, weighted, labeled, sparse, or dense. Adjacency matrices provide constant-time edge tests but require quadratic memory; adjacency lists use memory proportional to vertices and edges and are usually best for sparse graphs. BFS explores layers and finds shortest paths in unweighted graphs. DFS supports systematic exploration, component detection, cycle detection, and topological ordering. Dijkstra’s algorithm solves single-source shortest paths with nonnegative weights, Bellman–Ford permits negative edges, and Floyd–Warshall computes all-pairs shortest paths. Kruskal’s and Prim’s algorithms construct minimum spanning trees, which minimize total connection cost rather than individual route cost. Topological ordering applies only to directed acyclic graphs. Effective graph engineering also requires careful validation, complexity analysis, privacy protection, and awareness of application-specific constraints. Key TermsGraph: A structure consisting of vertices and edges. Vertex: An individual node or object in a graph. Edge: A connection between two vertices. Directed graph: A graph whose edges have direction. Undirected graph: A graph whose edges represent two-way relationships. Weighted graph: A graph whose edges have numerical values. Labeled graph: A graph whose vertices or edges carry descriptive attributes. Degree: The number of edges incident to an undirected vertex. Path: A sequence of vertices connected by edges. Cycle: A closed path that returns to its starting vertex. Adjacency matrix: A two-dimensional table recording pairwise adjacency or weights. Adjacency list: A collection of neighbor lists, one for each vertex. Breadth-first search: A queue-based, layer-by-layer traversal. Depth-first search: A traversal that explores deeply before backtracking. Connected component: A maximal set of mutually reachable vertices in an undirected graph. Shortest path: A minimum-cost path between vertices. Minimum spanning tree: A least-weight tree connecting every vertex of a connected undirected graph. Topological ordering: A dependency-respecting order of a directed acyclic graph. Relaxation: The operation of improving a tentative shortest-path distance. Disjoint-set union: A structure for maintaining dynamically merging sets and detecting cycles. Review QuestionsShort Answer Questions- What is the difference between a directed and an undirected graph?
- Why are adjacency lists usually suitable for sparse graphs?
- What property of edge weights is required by Dijkstra’s algorithm?
- What does a topological ordering represent?
- State one difference between a shortest-path tree and a minimum spanning tree.
Long Answer Questions- Explain BFS and DFS, including their data structures, applications, and time complexities.
- Compare adjacency matrices, adjacency lists, and edge lists for different graph densities and operations.
- Describe Dijkstra’s, Bellman–Ford, and Floyd–Warshall algorithms and identify when each should be used.
- Explain Kruskal’s and Prim’s minimum-spanning-tree algorithms and the role of cycle detection.
- Explain how directed and undirected cycle detection differ.
Analytical / Application Questions- Design a graph model for a university course-prerequisite system. Identify the vertex and edge types, choose a representation, and explain how cycles would be detected.
- A logistics network has nonnegative travel times but is sparse and contains thousands of locations. Select an algorithm for one-source routing and justify the representation and complexity.
- A company wants both the cheapest total fiber installation plan and the fastest route between offices. Explain why these are different graph problems and recommend algorithms for each.
Multiple Choice Questions with AnswersQuestion 1Which representation generally requires O(n²) memory for a graph with n vertices? A. Adjacency matrix B. Adjacency list C. Edge list D. Disjoint-set forest Correct Answer: A. Adjacency matrix Question 2Which traversal finds minimum-edge paths from a source in an unweighted graph? A. Depth-first search B. Breadth-first search C. Kruskal’s algorithm D. Floyd–Warshall only Correct Answer: B. Breadth-first search Question 3Dijkstra’s algorithm is guaranteed to be correct when edge weights are: A. All negative B. Nonnegative C. All distinct D. Equal to one Correct Answer: B. Nonnegative Question 4What does an edge to a currently explored ancestor indicate during directed DFS? A. A spanning tree B. A negative edge C. A directed cycle D. A topological ordering Correct Answer: C. A directed cycle Question 5A minimum spanning tree of a connected graph with n vertices contains how many edges? A. n − 1 B. n C. 2n D. n² Correct Answer: A. n − 1 Question 6Which algorithm is designed to support negative edge weights, provided there is no reachable negative cycle? A. BFS B. Dijkstra’s algorithm C. Bellman–Ford D. Prim’s algorithm Correct Answer: C. Bellman–Ford Question 7A topological ordering exists exactly when a directed graph is: A. Complete B. Acyclic C. Undirected D. Weighted Correct Answer: B. Acyclic Question 8For edges A→B with weight 4, A→C with weight 1, and C→B with weight 2, what is the shortest distance from A to B? A. 1 B. 2 C. 3 D. 4 Correct Answer: C. 3 Question 9Which algorithm computes shortest paths between every pair using a three-level intermediate-vertex recurrence? A. Floyd–Warshall B. Kruskal C. BFS D. Kahn’s algorithm Correct Answer: A. Floyd–Warshall Question 10What is the main purpose of a disjoint-set union structure in Kruskal’s algorithm? A. To sort vertices alphabetically B. To detect whether adding an edge creates a cycle C. To calculate vertex labels D. To store all-pairs distances Correct Answer: B. To detect whether adding an edge creates a cycle
|