Remove a node from the graph
(&mut self, node_id: &NodeId)
| 210 | |
| 211 | /// Remove a node from the graph |
| 212 | pub fn remove_node(&mut self, node_id: &NodeId) -> GraphBitResult<()> { |
| 213 | if self.nodes.remove(node_id).is_none() { |
| 214 | return Err(GraphBitError::graph(format!("Node {node_id} not found"))); |
| 215 | } |
| 216 | |
| 217 | // Remove edges involving this node |
| 218 | self.edges |
| 219 | .retain(|(from, to, _)| from != node_id && to != node_id); |
| 220 | |
| 221 | // Update adjacency maps incrementally for the removed node. |
| 222 | // Remove any outgoing entries for this node and drop this node from predecessors. |
| 223 | if let Some(successors) = self.outgoing.remove(node_id) { |
| 224 | for successor in successors { |
| 225 | if let Some(predecessors) = self.incoming.get_mut(&successor) { |
| 226 | predecessors.retain(|source| source != node_id); |
| 227 | if predecessors.is_empty() { |
| 228 | self.incoming.remove(&successor); |
| 229 | } |
| 230 | } |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | // Remove any incoming entries for this node and drop this node from successors. |
| 235 | if let Some(predecessors) = self.incoming.remove(node_id) { |
| 236 | for predecessor in predecessors { |
| 237 | if let Some(successors) = self.outgoing.get_mut(&predecessor) { |
| 238 | successors.retain(|target| target != node_id); |
| 239 | if successors.is_empty() { |
| 240 | self.outgoing.remove(&predecessor); |
| 241 | } |
| 242 | } |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | // Rebuild full graph/index structures to avoid stale NodeIndex entries |
| 247 | self.rebuild_petgraph_and_id_maps()?; |
| 248 | self.refresh_adjacency_from_edges(); |
| 249 | self.rebuild_name_map_from_nodes(); |
| 250 | |
| 251 | // Invalidate caches since graph structure changed |
| 252 | self.invalidate_caches(); |
| 253 | |
| 254 | Ok(()) |
| 255 | } |
| 256 | |
| 257 | /// Get a node by ID |
| 258 | #[inline] |