A graph $\mathcal{G}=(\mathcal{V},\mathcal{E})$ may be represented in central memory as follows:
an associative array (hash table) $V$ gives for any $v\in \mathcal{V}$ the list of its neighbors $V[v]$, each of these lists being represented as a dynamic array;
another associative array $E$ gives, for any $(u,v)\in \mathcal{E}$, the index of $v$ in $V[u]$.
This structure is very appealing if many graph updates (vertex and/or edge additions and/or removals) are performed. Indeed, graph updates may be performed in constant time (details below), and the whole structure takes only linear space. In addition, testing edge presence is in constant time and parsing node neighborhoods is optimal.
The literature on dynamic graph structures is very rich (see examples below). Yet, I can't find any (formal or empirical) analysis of this simple structure anywhere.
Does anyone have a pointer to such a study? If not, is this because people focus on worst case complexity only, and avoid hash tables for this reason? or because they assume only few graph editions are performed? or because it is considered too space costly? ...
Linear time updates are obtained as follows:
adding vertex $x$ is just adding the key $x$ to the associative array $V$, with an empty dynamic array as associated value;
removing vertex $x$ is just removing key $x$ from the associative array $V$ (assuming it has no edge at removal time);
adding edge $(x,y)$ is just adding $y$ to the end of the dynamic array $V[x]$ and setting $E[x,y]$ to the correct value, $len(V[x])-1$;
removing edge $(x,y)$ is slightly more subtle if $x$ has more than one neighbor; it consists in moving the last element $z$ of $V[x]$ to the position of $y$ and removing the last element of $V[x]$, which may be done efficiently thanks to the associative array $E$:
- $z \gets V[x][len(V[x])-1];$
- $V[x][E[x,y]] \gets z;$
- $E[x,z] \gets E[x,y];$
- remove last element of $V[x]$;
- remove key $(x,y)$ from $E$.
Operations on dynamic arrays are in $O(1)$ amortized time, and operations on associative arrays (i.e. hash tables) are in $O(1)$ expected time. Therefore all operations above are in constant time. Testing edge existence is in constant time too (hash table access), and one may also optimally parse the neighborhood of any vertex (it is an array). In addition, the whole data structure needs linear space $O(|\mathcal{V}|+|\mathcal{E}|)$ only, as hash tables and dynamic arrays do.
The literature on dynamic graph representations does not seem to consider the structure above, see for instance:
- On dynamic succinct graph representations by Miguel E. Coimbra, Alexandre P. Francisco, Luís M. S. Russo, Guillermo de Bernardo, Susana Ladra, Gonzalo Navarro
- CSR++: A Fast, Scalable, Update-Friendly Graph Data Structure by Soukaina Firmli, Vasileios Trigonakis, Jean-Pierre Lozi, Iraklis Psaroudakis, Alexander Weld, Dalila Chiadmi, Sungpack Hong, Hassan Chafi
- Low-Latency Graph Streaming Using Compressed Purely-Functional Trees by Laxman Dhulipala, Julian Shun, Guy Blelloch
Likewise, popular graph libraries do not seem to use this data structure, even performance-oriented ones that allow graph updates, like Networkit.