1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
//! Structural analysis algorithms for graph topology.
//!
//! This module provides algorithms for analyzing the structural properties of graphs,
//! including connectivity, cycles, and degree distributions. These algorithms help
//! understand the overall shape and topology of a graph.
//!
//! # Available Algorithms
//!
//! - [`connected_components`] - Find all connected components in the graph
//! - [`find_cycles_limited`] - Enumerate cycles up to a limit
//! - [`nodes_by_degree`] - Rank nodes by degree (hub detection)
//!
//! # When to Use Structural Analysis
//!
//! - **Connected Components**: Graph connectivity analysis, finding isolated clusters,
//! understanding graph fragmentation
//! - **Cycle Finding**: Detect feedback loops, find circular dependencies, analyze
//! strongly connected components
//! - **Degree Ranking**: Find hub nodes, identify influential connectors, analyze
//! network topology
use VecDeque;
use crate::;
/// Finds all connected components in the graph using BFS.
///
/// A connected component is a maximal subgraph where any two nodes are connected
/// by a path. This function uses bidirectional BFS (both incoming and outgoing edges).
///
/// # Arguments
/// * `graph` - The graph to analyze
///
/// # Returns
/// Vector of components, where each component is a sorted vector of node IDs.
/// Components are sorted by their smallest node ID.
///
/// # Complexity
/// Time: O(|V| + |E|) - visits each node and edge once
/// Space: O(|V|) for visited set and BFS queue
///
/// # Example
/// ```rust
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use sqlitegraph::{SqliteGraph, algo::connected_components};
/// let graph = SqliteGraph::open_in_memory()?;
/// // ... add nodes and edges ...
/// let components = connected_components(&graph)?;
/// # Ok(())
/// # }
/// ```
/// Finds cycles in the graph up to a specified limit.
///
/// Uses depth-first search to enumerate cycles starting from each node.
/// Cycles are normalized (rotated to start with smallest node) and deduplicated.
///
/// # Arguments
/// * `graph` - The graph to analyze
/// * `limit` - Maximum number of cycles to find (0 returns empty result)
///
/// # Returns
/// Vector of cycles, where each cycle is a vector of node IDs starting and ending
/// with the same node. Cycles are sorted for determinism.
///
/// # Complexity
/// Time: O(limit * (|V| + |E|)) in practice, but worst-case exponential
/// Space: O(|V|) for DFS stack and cycle paths
///
/// # Caveats
/// - May return duplicate cycles in symmetric graphs
/// - Does not guarantee finding all cycles (stops at limit)
/// - Performance degrades on dense graphs with many cycles
///
/// # Example
/// ```rust
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use sqlitegraph::{SqliteGraph, algo::find_cycles_limited};
/// let graph = SqliteGraph::open_in_memory()?;
/// // ... add nodes and edges ...
/// let cycles = find_cycles_limited(&graph, 10)?;
/// # Ok(())
/// # }
/// ```
/// Computes node degrees (total number of incoming + outgoing edges).
///
/// Returns all nodes sorted by their degree, useful for finding hubs (high-degree nodes)
/// or isolates (zero-degree nodes) in the graph.
///
/// # Arguments
/// * `graph` - The graph to analyze
/// * `descending` - If true, sort highest degree first; if false, sort lowest first
///
/// # Returns
/// Vector of (node_id, degree) tuples sorted by degree. Ties are broken by node ID.
///
/// # Complexity
/// Time: O(|V| + |E|) - visits each node and counts edges
/// Space: O(|V|) for degree storage
///
/// # Example
/// ```rust
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use sqlitegraph::{SqliteGraph, algo::nodes_by_degree};
/// let graph = SqliteGraph::open_in_memory()?;
/// // ... add nodes and edges ...
/// let degrees = nodes_by_degree(&graph, true)?;
/// # Ok(())
/// # }
/// ```
/// Normalizes cycles for deterministic output.
///
/// Rotates each cycle so it starts with the smallest node, then sorts
/// all cycles lexicographically.