dsa_rust/graphs/adjacency_list.rs
1use std::cmp::PartialEq;
2
3pub struct Node<T, M> {
4 data: T,
5 // Simple adjacency list structuring
6 links: Vec<Link<M>>,
7 // Adjacency map structring provides
8 // O(1) access for the get_edge(u, v) operation
9 //edges: std::collections::HashMap<Link<'a, T, X>>
10}
11impl<T, M> Node<T, M> {
12 fn new(data: T) -> Node<T, M> {
13 Node {
14 data,
15 links: Vec::new(),
16 }
17 }
18}
19impl<T, M> PartialEq for Node<T, M>
20where
21 T: PartialEq,
22{
23 fn eq(&self, other: &Self) -> bool {
24 self.data == other.data
25 }
26}
27
28#[allow(dead_code)]
29pub struct Link<M> {
30 //destination: &'a Node<'a, T, X>,
31 destination: usize,
32 metadata: Option<M>, // For weighted graphs
33}
34impl<M> Link<M> {
35 //fn new(destination: &'a Node<'a, T, X>, metadata: Option<X>) -> Self {
36 fn new(destination: usize, metadata: Option<M>) -> Self {
37 Link {
38 destination,
39 metadata,
40 }
41 }
42}
43//impl<M: PartialEq> PartialEq for Link<M> {
44// fn eq(&self, other: &Self) -> bool {
45// self.destination == other.destination &&
46// self.metadata == other.metadata
47// }
48//}
49
50/// Represents a pointer bag design for an adjacency list graph representation.
51/// Nodes are identified by stable `Vec` indices for the lifetime of the graph.
52//struct AdjacencyList<'a, T, X>(Vec<Node<'a, T, X>>);
53pub struct AdjacencyList<T, M> {
54 bag: Vec<Node<T, M>>,
55}
56impl<T, M> Default for AdjacencyList<T, M>
57where
58 T: PartialEq,
59{
60 fn default() -> Self {
61 Self::new()
62 }
63}
64impl<T, M> AdjacencyList<T, M>
65where
66 T: PartialEq,
67{
68 // Factories
69 ////////////
70
71 /// Creates a new, empty graph
72 pub fn new() -> Self {
73 //AdjacencyList(Vec::new())
74 AdjacencyList { bag: Vec::new() }
75 }
76
77 // Mutators
78 ///////////
79
80 /// Creates and adds a new vertex for the specified data
81 pub fn add_node(&mut self, data: T) -> usize {
82 let node = Node::new(data);
83 self.bag.push(node);
84 self.bag.len() - 1
85 }
86
87 /// Creates and adds a new edge from an originating vertex to a
88 /// destination vertex with an optional metadata element `M` such
89 /// as a weight. Origin and destination arguments are positional
90 /// for directed graphs.
91 pub fn add_directed_link(&mut self, origin: usize, destination: usize, metadata: Option<M>) {
92 // Create the new Link
93 let link = Link::new(destination, metadata);
94
95 // Add the link to the origin node's list of links
96 self.bag[origin].links.push(link);
97 }
98
99 /// Creates and adds a new _undirected_ edge from one node to another
100 /// node with an optional metadata element `M` such
101 /// as a weight.
102 pub fn add_undirected_link(&mut self, first: usize, second: usize, metadata: Option<M>)
103 where
104 M: Clone,
105 {
106 // Create the new Link
107 let link = Link::new(second, metadata.clone());
108
109 // Add the link to the origin node's list of links
110 self.bag[first].links.push(link);
111
112 // Create the new Link
113 let link = Link::new(first, metadata);
114
115 // Add the link to the destination node's list of links
116 self.bag[second].links.push(link);
117 }
118
119 //remove_vertex(v)` Removes vertex `v` and all of its incident edges
120 //remove_edge(e)` Removes edge `e`
121
122 // Accessors
123 ////////////
124
125 /// Returns a reference to a node for a given index.
126 pub fn get_node(&self, index: usize) -> Option<&Node<T, M>> {
127 // Handles len check internally and returns Option by default
128 // because some APIs are better than others
129 self.bag.get(index)
130 }
131
132 #[allow(dead_code)]
133 /// Locates the node's stable index by value in _O(n)_ time.
134 fn get_node_index(&self, node: &Node<T, M>) -> Option<usize> {
135 for (i, val) in self.bag.iter().enumerate() {
136 if val.data == node.data {
137 return Some(i);
138 }
139 }
140 None
141 }
142
143 /// Returns the number of nodes in the graph
144 pub fn num_nodes(&self) -> usize {
145 self.bag.len()
146 }
147
148 /// Returns the number of unique links in the graph
149 pub fn num_links(&self) -> usize {
150 self.links().len()
151 }
152
153 // /// Returns the edge between vertices `u` and `v`, this can be positional for directed graphs, and symmetric for undirected graphs
154 //pub fn get_link(&self, origin: usize, destination: usize) {}
155
156 // /// Returns an array containing the two endpoint
157 // /// vertides of edge `e`, this can be positional for directed graphs,
158 // /// and symmetric for undirected graphs
159 //pub fn get_nodes(&self, link: usize) -> (&Node<T, M>, &Node<T, M>) {}
160
161 //opposite(v, e)` Returns the pair vertex of an edge `e` incident to vertex `v`
162 //is_adjacent(u, v)` Returns a Boolean to indicate if vertices `u` and `v` are adjacent
163 //out_degree(v)` Returns the number of outgoing edges from vertex `v`
164 //in_degree(v)` Returns the number of incoming edges from vertex `v`
165
166 /// Returns an iterable collection over all vertices in the graph
167 pub fn nodes(&self) -> &Vec<Node<T, M>> {
168 &self.bag
169 }
170
171 /// Returns an iterator over all vertices in the graph
172 pub fn nodes_iter(&self) -> impl Iterator<Item = &Node<T, M>> {
173 self.bag.iter()
174 }
175
176 // Returns an iteraterable collection over
177 //outgoing edges from vertex `v`
178 pub fn out_links(&self, index: usize) -> &[Link<M>] {
179 &self.bag[index].links
180 }
181
182 /// Returns an iterator over all outgoing links for a given node
183 pub fn out_links_iter(&self, index: usize) -> impl Iterator<Item = &Link<M>> {
184 self.bag[index].links.iter()
185 }
186
187 /// Returns an iterator over incoming links from a given node
188 pub fn in_links(&self, index: usize) -> Vec<&Link<M>> {
189 let mut list = Vec::new();
190 for node in self.bag.iter() {
191 for link in node.links.iter() {
192 if link.destination == index {
193 list.push(link)
194 }
195 }
196 }
197 list
198 }
199
200 /// Returns an iterator over all incoming links to a given node
201 pub fn in_links_iter(&self, index: usize) -> impl Iterator<Item = (&Node<T, M>, &Link<M>)> {
202 self.bag.iter().flat_map(move |node| {
203 node.links
204 .iter()
205 .filter(move |link| link.destination == index)
206 .map(move |link| (node, link))
207 })
208 }
209
210 /// Returns an iteratable collection over all links in the graph as
211 /// { (u, (u → v)) | u ∈ V, (u → v) ∈ Adj[u] }
212 pub fn links(&self) -> Vec<(&Node<T, M>, &Link<M>)> {
213 let mut links: Vec<(&Node<T, M>, &Link<M>)> = Vec::new();
214 for node in self.bag.iter() {
215 for link in node.links.iter() {
216 links.push((node, link))
217 }
218 }
219 links
220 }
221
222 /// Returns an iterator over all links in the graph
223 pub fn links_iter(&self) -> impl Iterator<Item = (&Node<T, M>, &Link<M>)> {
224 self.bag
225 .iter()
226 .flat_map(|node| node.links.iter().map(move |link| (node, link)))
227 }
228}
229
230// (Explicit) Iterator Structs
231//////////////////////////////
232
233//pub struct Links {}
234//impl Links {}
235//impl Iterator for Links{
236// type Item = ;
237// fn next(&mut self) -> Option<Self::Item> {}
238//}
239//pub struct Union<'a, K> {
240// // Used "raw" for its "free" operations
241// lhs: &'a probing_hash_table::HashMap<K, ()>,
242// // Create explicit iterators outside of the next() implementation
243// lhs_iter: probing_hash_table::Keys<'a, K, ()>,
244// rhs_iter: probing_hash_table::Keys<'a, K, ()>,
245//}
246//impl<'a, K> Union<'a, K> {
247// // Constructor that takes map references to create iterators outside of the next()
248// // implementation
249// fn build(
250// lhs: &'a probing_hash_table::HashMap<K, ()>,
251// rhs: &'a probing_hash_table::HashMap<K, ()>,
252// ) -> Union<'a, K>
253// where
254// K: Debug + Eq + Hash + PartialEq,
255// {
256// Union {
257// lhs_iter: lhs.keys(),
258// rhs_iter: rhs.keys(),
259// lhs,
260// }
261// }
262//}
263//impl<'a, K> Iterator for Union<'a, K>
264//where
265// K: Debug + Eq + Hash,
266//{
267// type Item = &'a K;
268//
269// fn next(&mut self) -> Option<Self::Item> {
270// // Yield elements from lhs iterator
271// if let Some(key) = self.lhs_iter.next() {
272// return Some(key);
273// }
274//
275// // Then yield only unique elements from the rhs iterator
276// self.rhs_iter.by_ref().find(|&key| !self.lhs.contains(key))
277// //while let Some(key) = self.rhs_iter.next() {
278// // if !self.lhs.contains(key) {
279// // return Some(key);
280// // }
281// //}
282// //None
283// }
284//}
285
286#[cfg(test)]
287mod graph_tests {
288 use super::*;
289
290 #[test]
291 fn one() {
292 // 1) Build the following edgeless (unconnected) graph:
293 //
294 // [A] [B] [C] [D]
295 //
296 // [E] [F] [G] [H]
297 //
298 // [I] [J] [K] [L]
299 //
300 // [M] [N] [O] [P]
301
302 let mut graph = AdjacencyList::<&str, usize>::new();
303 for name in [
304 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P",
305 ] {
306 graph.add_node(name);
307 }
308
309 // 2) Add links to create the following connected, undirected graph:
310 //
311 // [A] --- [B] --- [C] --- [D]
312 // | \ | | / |
313 // | \ | | / |
314 // | \ | | / |
315 // | \ | | / |
316 // [E] --- [F] [G] [H]
317 // | / / | \ |
318 // | / / | \ |
319 // | / / | \ |
320 // | / / | \ |
321 // [I] --- [J] --- [K] [L]
322 // | \ / | |
323 // | \ / | |
324 // | \ / | |
325 // | \ / | |
326 // [M] --- [N] [O] [P]
327
328 graph.add_undirected_link(0, 1, None);
329 graph.add_undirected_link(1, 2, None);
330 graph.add_undirected_link(2, 3, None);
331 graph.add_undirected_link(3, 6, None);
332 graph.add_undirected_link(4, 0, None);
333 graph.add_undirected_link(4, 5, None);
334 graph.add_undirected_link(5, 0, None);
335 graph.add_undirected_link(5, 1, None);
336 graph.add_undirected_link(5, 8, None);
337 graph.add_undirected_link(6, 2, None);
338 graph.add_undirected_link(6, 9, None);
339 graph.add_undirected_link(6, 11, None);
340 graph.add_undirected_link(7, 3, None);
341 graph.add_undirected_link(8, 4, None);
342 graph.add_undirected_link(8, 12, None);
343 graph.add_undirected_link(9, 8, None);
344 graph.add_undirected_link(10, 9, None);
345 graph.add_undirected_link(10, 6, None);
346 graph.add_undirected_link(10, 14, None);
347 graph.add_undirected_link(11, 7, None);
348 graph.add_undirected_link(11, 15, None);
349 graph.add_undirected_link(12, 13, None);
350 graph.add_undirected_link(13, 8, None);
351 graph.add_undirected_link(13, 10, None);
352
353 // 3) Traverse the graph with DFS:
354 //
355 // [A] --> [B] --> [C] --> [D]
356 // ^ ^ ^ ^ / ^
357 // | \ | | / |
358 // | \ | | / |
359 // | \ | | v |
360 // [E] --> [F] [G] [H]
361 // ^ / / ^ \ ^
362 // | / / | \ |
363 // | / / | \ |
364 // | v v | v |
365 // [I] <-- [J] <-- [K] [L]
366 // | ^ ^| |
367 // | \ / | |
368 // | \ / | |
369 // v \ / v v
370 // [M] --> [N] [O] [P]
371 //
372 // With the following traversal order:
373 // A -> B (FE),
374 // B -> C (FE),
375 // C -> D (FE),
376 // D -> G (FE),
377 // G -> C (FE),
378
379 let _a: [usize; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
380 }
381}