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