commit 268daf6c9359a0b1fa0bee54bf73d965068e1e17 Author: cy Date: Mon Jan 13 22:49:04 2025 -0500 implement graph diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..d34ca04 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "skiena" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..190091d --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "skiena" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/src/graph.rs b/src/graph.rs new file mode 100644 index 0000000..4998b11 --- /dev/null +++ b/src/graph.rs @@ -0,0 +1,80 @@ +use std::rc::Rc; + +const MAXV: usize = 1000; + +#[derive(Clone)] +struct Edgenode { + #[allow(unused)] + weight: i32, // Edge weight, if any + + y: i32, // Adjacency info + next: Option>, // next edge in list +} + +pub struct Graph { + edges: Vec>>, // adjacency info + degree: Vec, // outdegree of each vertex + nvertices: i32, // number of vertices in graph + nedges: i32, // number of edges in graph + directed: bool, // is the graph directed? +} + +impl Graph { + pub fn new(directed: bool) -> Self { + Self { + nvertices: 0, + nedges: 0, + directed, + degree: vec![0; MAXV], + edges: vec![None; MAXV], + } + } + + fn insert_edge(&mut self, x: usize, y: i32, directed: bool) { + let p = Rc::new(Edgenode { + y, + weight: 0, + next: self.edges[x].clone(), + }); + self.edges[x] = Some(p); + self.degree[x] += 1; + if directed { + self.nedges += 1; + } else { + self.insert_edge(y.try_into().unwrap(), x.try_into().unwrap(), true); + } + } + + pub fn print_graph(&self) { + for i in 0..self.nvertices as usize { + print!("{} -->", i); + let mut p_opt = self.edges[i].clone(); + while let Some(p) = p_opt { + print!(" {}", p.y); + p_opt = p.next.clone(); + } + println!(); + } + } + + pub fn read_graph(&mut self, data: String) { + self._read_graph(data, self.directed); + } + + fn _read_graph(&mut self, data: String, directed: bool) { + // reverse here so that we can pop() later + let mut data_parsed: Vec<&str> = data.split(' ').rev().collect(); + + // The first two digits in `data` are `nvertices` and the total number of edges + // between them + self.nvertices = data_parsed.pop().unwrap().parse().expect("invalid int"); + let num_edges: i32 = data_parsed.pop().unwrap().parse().expect("invalid int"); + + // After that, parse edges as (x, y) + for _ in 0..num_edges { + let x: i32 = data_parsed.pop().unwrap().parse().unwrap(); + let y: i32 = data_parsed.pop().unwrap().parse().unwrap(); + self.insert_edge(x.try_into().unwrap(), y, directed); + } + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b4394c1 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,24 @@ +use crate::graph::Graph; + +mod graph; + +fn main() { + let mut graph = Graph::new(true); + let data = "5 14 \ + 1 2 \ + 1 5 \ + 2 1 \ + 2 5 \ + 2 3 \ + 2 4 \ + 3 2 \ + 3 4 \ + 4 2 \ + 4 5 \ + 4 3 \ + 5 4 \ + 5 1 \ + 5 2"; + graph.read_graph(data.to_string()); + graph.print_graph(); +}