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}