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}