Skip to main content
remove pub on edge nodes
Source Link
pub struct Edge {
    pub node_a: i32,
    pub node_b: i32,
}

impl Edge {
    #[inline]
    pub fn new(node_a: i32, node_b: i32) -> Self {
        Edge {
            node_a: node_a,
            node_b: node_b,
        }
    }

    //if base_node is neither of the edge nodes then the result is considered random
    pub fn get_adj_node(&self, base_node: i32) -> i32 {
        if base_node == self.node_a {
            self.node_b
        } else {
            self.node_a
        }
    }
}
pub struct Edge {
    pub node_a: i32,
    pub node_b: i32,
}

impl Edge {
    #[inline]
    pub fn new(node_a: i32, node_b: i32) -> Self {
        Edge {
            node_a: node_a,
            node_b: node_b,
        }
    }

    //if base_node is neither of the edge nodes then the result is considered random
    pub fn get_adj_node(&self, base_node: i32) -> i32 {
        if base_node == self.node_a {
            self.node_b
        } else {
            self.node_a
        }
    }
}
pub struct Edge {
    node_a: i32,
    node_b: i32,
}

impl Edge {
    #[inline]
    pub fn new(node_a: i32, node_b: i32) -> Self {
        Edge {
            node_a: node_a,
            node_b: node_b,
        }
    }

    //if base_node is neither of the edge nodes then the result is considered random
    pub fn get_adj_node(&self, base_node: i32) -> i32 {
        if base_node == self.node_a {
            self.node_b
        } else {
            self.node_a
        }
    }
}
Source Link

Checking if a graph is fully connected

After reading the rust book for some time I decided to create my first program which implements a graph.

There are a few things I was wondering about, such as if the file structure is appropriate (the graph.rs just containing a few mod statements feels weird).

Also to store pointers to the edges I had to use Rc and I am not sure if that is the correct choice?

And finally I'm also wondering if there is a more idiomatic rust way to write certain code ?

Other comments are welcome as well of course.

main.rs:

use crate::graph::edge::Edge;
use crate::graph::graph::Graph;
use crate::graph::node::Node;
use std::collections::HashMap;
use std::rc::Rc;

pub mod graph;

fn main() {
    let g = create_graph();
    println!("graph connected: {}", g.is_fully_connected());
}

fn create_graph() -> Graph {
    let n: Vec<Node> = vec![Node::new(), Node::new(), Node::new()];

    let edge1 = &Rc::new(Edge::new(0, 1));
    let edge2 = &Rc::new(Edge::new(0, 2));
    let edge3 = &Rc::new(Edge::new(1, 2));

    let mut neighbors = HashMap::new();

    let neighbors0 = vec![Rc::clone(edge1), Rc::clone(edge2)];
    let neighbors1 = vec![Rc::clone(edge1), Rc::clone(edge3)];
    let neighbors2 = vec![Rc::clone(edge2), Rc::clone(edge3)];
    neighbors.insert(0, neighbors0);
    neighbors.insert(1, neighbors1);
    neighbors.insert(2, neighbors2);

    Graph::new(n, neighbors)
}

graph.rs:

pub mod graph;
pub mod edge;
pub mod node;

graph/node.rs:

pub struct Node {
    //TODO coordinates
}

impl Node {
    #[inline]
    pub fn new() -> Self {
        Node {}
    }
}

graph/edge.rs

pub struct Edge {
    pub node_a: i32,
    pub node_b: i32,
}

impl Edge {
    #[inline]
    pub fn new(node_a: i32, node_b: i32) -> Self {
        Edge {
            node_a: node_a,
            node_b: node_b,
        }
    }

    //if base_node is neither of the edge nodes then the result is considered random
    pub fn get_adj_node(&self, base_node: i32) -> i32 {
        if base_node == self.node_a {
            self.node_b
        } else {
            self.node_a
        }
    }
}

graph/graph.rs:

use super::edge::Edge;
use super::node::Node;
use std::collections::HashMap;
use std::collections::HashSet;
use std::rc::Rc;

pub struct Graph {
    nodes: Vec<Node>,
    neighbors: HashMap<i32, Vec<Rc<Edge>>>, //node index to coinciding edges
}

impl Graph {
    pub fn new(nodes: Vec<Node>, neighbors: HashMap<i32, Vec<Rc<Edge>>>) -> Self {
        Graph {
            nodes: nodes,
            neighbors: neighbors,
        }
    }

    pub fn is_fully_connected(&self) -> bool {
        let mut index = 0;

        let mut stack = vec![index];
        let mut used = HashSet::from([index]);

        while !stack.is_empty() {
            index = stack.pop().unwrap();

            let neighbors = match self.neighbors.get(&index) {
                None => continue,
                Some(n) => n,
            };
    
            for edge in neighbors {
                let adj_node = edge.get_adj_node(index);
                if !used.contains(&adj_node) {
                    used.insert(adj_node);
                    stack.push(adj_node);
                }
            }
        }

        used.len() == self.nodes.len()
    }
}