Files
hello-algo/en/docs/chapter_graph/graph_operations.md
Yudong Jin b01036b09e Revisit the English version (#1885)
* Update giscus scroller.

* Refine English docs and landing page

* Sync the headings.

* Update landing pages.

* Update the avatar

* Update Acknowledgements

* Update landing pages.

* Update contributors.

* Update

* Fix the formula formatting.

* Fix the glossary.

* Chapter 6. Hashing

* Remove Chinese chars.

* Fix headings.

* Update giscus themes.

* fallback to default giscus theme to solve 429 many requests error.

* Add borders for callouts.

* docs: sync character encoding translations

* Update landing page media layout and i18n
2026-04-10 23:03:03 +08:00

6.1 KiB

Basic Operations on Graphs

Basic operations on graphs can be divided into operations on "edges" and operations on "vertices". Their implementations differ depending on whether the graph is represented as an "adjacency matrix" or an "adjacency list".

Implementation Based on Adjacency Matrix

Given an undirected graph with n vertices, the various operations are implemented as shown in the figure below.

  • Adding or removing an edge: Directly modify the specified edge in the adjacency matrix, using O(1) time. Since it is an undirected graph, both directions of the edge need to be updated simultaneously.
  • Adding a vertex: Add a row and a column at the end of the adjacency matrix and fill them all with $0$s, using O(n) time.
  • Removing a vertex: Delete a row and a column in the adjacency matrix. The worst case occurs when removing the first row and column, requiring (n-1)^2 elements to be "moved up and to the left", thus using O(n^2) time.
  • Initialization: Given n vertices, initialize a vertex list vertices of length n, using O(n) time; initialize an adjacency matrix adjMat of size n \times n, using O(n^2) time.

=== "<1>" Initialization, adding and removing edges, adding and removing vertices in adjacency matrix

=== "<2>" adjacency_matrix_add_edge

=== "<3>" adjacency_matrix_remove_edge

=== "<4>" adjacency_matrix_add_vertex

=== "<5>" adjacency_matrix_remove_vertex

The following is the implementation code for graphs represented using an adjacency matrix:

[file]{graph_adjacency_matrix}-[class]{graph_adj_mat}-[func]{}

Implementation Based on Adjacency List

Given an undirected graph with a total of n vertices and m edges, the various operations can be implemented as shown in the figure below.

  • Adding an edge: Add the edge at the end of the corresponding vertex's linked list, using O(1) time. Since it is an undirected graph, edges in both directions need to be added simultaneously.
  • Removing an edge: Find and remove the specified edge in the corresponding vertex's linked list, using O(m) time. In an undirected graph, edges in both directions need to be removed simultaneously.
  • Adding a vertex: Add a linked list to the adjacency list, with the new vertex as the head node, using O(1) time.
  • Removing a vertex: Traverse the entire adjacency list and remove all edges containing the specified vertex, using O(n + m) time.
  • Initialization: Create n vertices and 2m edges in the adjacency list, using O(n + m) time.

=== "<1>" Initialization, adding and removing edges, adding and removing vertices in adjacency list

=== "<2>" adjacency_list_add_edge

=== "<3>" adjacency_list_remove_edge

=== "<4>" adjacency_list_add_vertex

=== "<5>" adjacency_list_remove_vertex

The following code shows the adjacency list implementation. Compared with the figure above, the actual code differs in the following ways.

  • For convenience in adding and removing vertices, and to simplify the code, we use lists (dynamic arrays) instead of linked lists.
  • A hash table is used to store the adjacency list, where key is the vertex instance and value is the list (linked list) of adjacent vertices for that vertex.

Additionally, we use the Vertex class to represent vertices in the adjacency list for the following reason: if we used list indices to distinguish different vertices, as with adjacency matrices, then to delete the vertex at index i, we would need to traverse the entire adjacency list and decrement all indices greater than i by 1, which is very inefficient. However, if each vertex is a unique Vertex instance, deleting one vertex does not require modifying the others.

[file]{graph_adjacency_list}-[class]{graph_adj_list}-[func]{}

Efficiency Comparison

Assuming the graph has n vertices and m edges, the table below compares the time efficiency and space efficiency of adjacency matrices and adjacency lists. Note that the adjacency list (linked list) corresponds to the implementation used in this section, while the adjacency list (hash table) refers specifically to the implementation where all linked lists are replaced with hash tables.

Table   Comparison of adjacency matrix and adjacency list

Adjacency matrix Adjacency list (linked list) Adjacency list (hash table)
Determine adjacency O(1) O(n) O(1)
Add an edge O(1) O(1) O(1)
Remove an edge O(1) O(n) O(1)
Add a vertex O(n) O(1) O(1)
Remove a vertex O(n^2) O(n + m) O(n)
Memory space usage O(n^2) O(n + m) O(n + m)

Observing the table above, it appears that the adjacency list (hash table) has the best time efficiency and space efficiency. However, in practice, operating on edges in the adjacency matrix is more efficient, requiring only a single array access or assignment operation. Overall, adjacency matrices embody the principle of "trading space for time", while adjacency lists embody "trading time for space".