图(graph)

  1. use std::collections::{HashMap, HashSet};
  2. use std::fmt;
  3. #[derive(Debug, Clone)]
  4. pub struct NodeNotInGraph;
  5. impl fmt::Display for NodeNotInGraph {
  6. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  7. write!(f, "accessing a node that is not in the graph")
  8. }
  9. }
  10. pub struct DirectedGraph {
  11. adjacency_table: HashMap<String, Vec<(String, i32)>>,
  12. }
  13. impl Graph for DirectedGraph {
  14. fn new() -> DirectedGraph {
  15. DirectedGraph {
  16. adjacency_table: HashMap::new(),
  17. }
  18. }
  19. fn adjacency_table_mutable(&mut self) -> &mut HashMap<String, Vec<(String, i32)>> {
  20. &mut self.adjacency_table
  21. }
  22. fn adjacency_table(&self) -> &HashMap<String, Vec<(String, i32)>> {
  23. &self.adjacency_table
  24. }
  25. }
  26. pub struct UndirectedGraph {
  27. adjacency_table: HashMap<String, Vec<(String, i32)>>,
  28. }
  29. impl Graph for UndirectedGraph {
  30. fn new() -> UndirectedGraph {
  31. UndirectedGraph {
  32. adjacency_table: HashMap::new(),
  33. }
  34. }
  35. fn adjacency_table_mutable(&mut self) -> &mut HashMap<String, Vec<(String, i32)>> {
  36. &mut self.adjacency_table
  37. }
  38. fn adjacency_table(&self) -> &HashMap<String, Vec<(String, i32)>> {
  39. &self.adjacency_table
  40. }
  41. fn add_edge(&mut self, edge: (&str, &str, i32)) {
  42. self.add_node(edge.0);
  43. self.add_node(edge.1);
  44. self.adjacency_table
  45. .entry(edge.0.to_string())
  46. .and_modify(|e| {
  47. e.push((edge.1.to_string(), edge.2));
  48. });
  49. self.adjacency_table
  50. .entry(edge.1.to_string())
  51. .and_modify(|e| {
  52. e.push((edge.0.to_string(), edge.2));
  53. });
  54. }
  55. }
  56. pub trait Graph {
  57. fn new() -> Self;
  58. fn adjacency_table_mutable(&mut self) -> &mut HashMap<String, Vec<(String, i32)>>;
  59. fn adjacency_table(&self) -> &HashMap<String, Vec<(String, i32)>>;
  60. fn add_node(&mut self, node: &str) -> bool {
  61. match self.adjacency_table().get(node) {
  62. None => {
  63. self.adjacency_table_mutable()
  64. .insert((*node).to_string(), Vec::new());
  65. true
  66. }
  67. _ => false,
  68. }
  69. }
  70. fn add_edge(&mut self, edge: (&str, &str, i32)) {
  71. self.add_node(edge.0);
  72. self.add_node(edge.1);
  73. self.adjacency_table_mutable()
  74. .entry(edge.0.to_string())
  75. .and_modify(|e| {
  76. e.push((edge.1.to_string(), edge.2));
  77. });
  78. }
  79. fn neighbours(&self, node: &str) -> Result<&Vec<(String, i32)>, NodeNotInGraph> {
  80. match self.adjacency_table().get(node) {
  81. None => Err(NodeNotInGraph),
  82. Some(i) => Ok(i),
  83. }
  84. }
  85. fn contains(&self, node: &str) -> bool {
  86. self.adjacency_table().get(node).is_some()
  87. }
  88. fn nodes(&self) -> HashSet<&String> {
  89. self.adjacency_table().keys().collect()
  90. }
  91. fn edges(&self) -> Vec<(&String, &String, i32)> {
  92. let mut edges = Vec::new();
  93. for (from_node, from_node_neighbours) in self.adjacency_table() {
  94. for (to_node, weight) in from_node_neighbours {
  95. edges.push((from_node, to_node, *weight));
  96. }
  97. }
  98. edges
  99. }
  100. }
  101. #[cfg(test)]
  102. mod test_undirected_graph {
  103. use super::Graph;
  104. use super::UndirectedGraph;
  105. #[test]
  106. fn test_add_edge() {
  107. let mut graph = UndirectedGraph::new();
  108. graph.add_edge(("a", "b", 5));
  109. graph.add_edge(("b", "c", 10));
  110. graph.add_edge(("c", "a", 7));
  111. let expected_edges = [
  112. (&String::from("a"), &String::from("b"), 5),
  113. (&String::from("b"), &String::from("a"), 5),
  114. (&String::from("c"), &String::from("a"), 7),
  115. (&String::from("a"), &String::from("c"), 7),
  116. (&String::from("b"), &String::from("c"), 10),
  117. (&String::from("c"), &String::from("b"), 10),
  118. ];
  119. for edge in expected_edges.iter() {
  120. assert_eq!(graph.edges().contains(edge), true);
  121. }
  122. }
  123. #[test]
  124. fn test_neighbours() {
  125. let mut graph = UndirectedGraph::new();
  126. graph.add_edge(("a", "b", 5));
  127. graph.add_edge(("b", "c", 10));
  128. graph.add_edge(("c", "a", 7));
  129. assert_eq!(
  130. graph.neighbours("a").unwrap(),
  131. &vec![(String::from("b"), 5), (String::from("c"), 7)]
  132. );
  133. }
  134. }
  135. #[cfg(test)]
  136. mod test_directed_graph {
  137. use super::DirectedGraph;
  138. use super::Graph;
  139. #[test]
  140. fn test_add_node() {
  141. let mut graph = DirectedGraph::new();
  142. graph.add_node("a");
  143. graph.add_node("b");
  144. graph.add_node("c");
  145. assert_eq!(
  146. graph.nodes(),
  147. [&String::from("a"), &String::from("b"), &String::from("c")]
  148. .iter()
  149. .cloned()
  150. .collect()
  151. );
  152. }
  153. #[test]
  154. fn test_add_edge() {
  155. let mut graph = DirectedGraph::new();
  156. graph.add_edge(("a", "b", 5));
  157. graph.add_edge(("c", "a", 7));
  158. graph.add_edge(("b", "c", 10));
  159. let expected_edges = [
  160. (&String::from("a"), &String::from("b"), 5),
  161. (&String::from("c"), &String::from("a"), 7),
  162. (&String::from("b"), &String::from("c"), 10),
  163. ];
  164. for edge in expected_edges.iter() {
  165. assert_eq!(graph.edges().contains(edge), true);
  166. }
  167. }
  168. #[test]
  169. fn test_neighbours() {
  170. let mut graph = DirectedGraph::new();
  171. graph.add_edge(("a", "b", 5));
  172. graph.add_edge(("b", "c", 10));
  173. graph.add_edge(("c", "a", 7));
  174. assert_eq!(
  175. graph.neighbours("a").unwrap(),
  176. &vec![(String::from("b"), 5)]
  177. );
  178. }
  179. #[test]
  180. fn test_contains() {
  181. let mut graph = DirectedGraph::new();
  182. graph.add_node("a");
  183. graph.add_node("b");
  184. graph.add_node("c");
  185. assert_eq!(graph.contains("a"), true);
  186. assert_eq!(graph.contains("b"), true);
  187. assert_eq!(graph.contains("c"), true);
  188. assert_eq!(graph.contains("d"), false);
  189. }
  190. }