1
- use std:: collections:: { HashMap , HashSet } ;
1
+ use std:: collections:: { hash_map :: Entry :: Vacant , HashMap , HashSet } ;
2
2
use std:: fmt;
3
+ use std:: hash:: Hash ;
3
4
4
5
#[ derive( Debug , Clone ) ]
5
6
pub struct NodeNotInGraph ;
@@ -10,147 +11,157 @@ impl fmt::Display for NodeNotInGraph {
10
11
}
11
12
}
12
13
13
- pub struct DirectedGraph {
14
- adjacency_table : HashMap < String , Vec < ( String , i32 ) > > ,
14
+ pub struct DirectedGraph < ' a , T > {
15
+ adjacency_table : HashMap < & ' a T , Vec < ( & ' a T , i32 ) > > ,
15
16
}
16
17
17
- impl Graph for DirectedGraph {
18
- fn new ( ) -> DirectedGraph {
18
+ impl < ' a , T > Graph < ' a , T > for DirectedGraph < ' a , T >
19
+ where
20
+ T : ' a + Eq + Hash ,
21
+ {
22
+ fn new ( ) -> DirectedGraph < ' a , T > {
19
23
DirectedGraph {
20
24
adjacency_table : HashMap :: new ( ) ,
21
25
}
22
26
}
23
- fn adjacency_table_mutable ( & mut self ) -> & mut HashMap < String , Vec < ( String , i32 ) > > {
27
+ fn adjacency_table_mutable ( & mut self ) -> & mut HashMap < & ' a T , Vec < ( & ' a T , i32 ) > > {
24
28
& mut self . adjacency_table
25
29
}
26
- fn adjacency_table ( & self ) -> & HashMap < String , Vec < ( String , i32 ) > > {
30
+ fn adjacency_table ( & self ) -> & HashMap < & ' a T , Vec < ( & ' a T , i32 ) > > {
27
31
& self . adjacency_table
28
32
}
29
33
}
30
34
31
- pub struct UndirectedGraph {
32
- adjacency_table : HashMap < String , Vec < ( String , i32 ) > > ,
35
+ pub struct UndirectedGraph < ' a , T > {
36
+ adjacency_table : HashMap < & ' a T , Vec < ( & ' a T , i32 ) > > ,
33
37
}
34
38
35
- impl Graph for UndirectedGraph {
36
- fn new ( ) -> UndirectedGraph {
39
+ impl < ' a , T > Graph < ' a , T > for UndirectedGraph < ' a , T >
40
+ where
41
+ T : ' a + Eq + Hash ,
42
+ {
43
+ fn new ( ) -> UndirectedGraph < ' a , T > {
37
44
UndirectedGraph {
38
45
adjacency_table : HashMap :: new ( ) ,
39
46
}
40
47
}
41
- fn adjacency_table_mutable ( & mut self ) -> & mut HashMap < String , Vec < ( String , i32 ) > > {
48
+ fn adjacency_table_mutable ( & mut self ) -> & mut HashMap < & ' a T , Vec < ( & ' a T , i32 ) > > {
42
49
& mut self . adjacency_table
43
50
}
44
- fn adjacency_table ( & self ) -> & HashMap < String , Vec < ( String , i32 ) > > {
51
+ fn adjacency_table ( & self ) -> & HashMap < & ' a T , Vec < ( & ' a T , i32 ) > > {
45
52
& self . adjacency_table
46
53
}
47
- fn add_edge ( & mut self , edge : ( & str , & str , i32 ) ) {
54
+ fn add_edge ( & mut self , edge : ( & ' a T , & ' a T , i32 ) ) {
48
55
self . add_node ( edge. 0 ) ;
49
56
self . add_node ( edge. 1 ) ;
50
57
51
- self . adjacency_table
52
- . entry ( edge. 0 . to_string ( ) )
53
- . and_modify ( |e| {
54
- e. push ( ( edge. 1 . to_string ( ) , edge. 2 ) ) ;
55
- } ) ;
56
- self . adjacency_table
57
- . entry ( edge. 1 . to_string ( ) )
58
- . and_modify ( |e| {
59
- e. push ( ( edge. 0 . to_string ( ) , edge. 2 ) ) ;
60
- } ) ;
58
+ self . adjacency_table . entry ( edge. 0 ) . and_modify ( |e| {
59
+ e. push ( ( edge. 1 , edge. 2 ) ) ;
60
+ } ) ;
61
+ self . adjacency_table . entry ( edge. 1 ) . and_modify ( |e| {
62
+ e. push ( ( edge. 0 , edge. 2 ) ) ;
63
+ } ) ;
61
64
}
62
65
}
63
66
64
- pub trait Graph {
67
+ pub trait Graph < ' a , T >
68
+ where
69
+ T : ' a + Eq + Hash ,
70
+ {
65
71
fn new ( ) -> Self ;
66
- fn adjacency_table_mutable ( & mut self ) -> & mut HashMap < String , Vec < ( String , i32 ) > > ;
67
- fn adjacency_table ( & self ) -> & HashMap < String , Vec < ( String , i32 ) > > ;
72
+ fn adjacency_table_mutable ( & mut self ) -> & mut HashMap < & ' a T , Vec < ( & ' a T , i32 ) > > ;
73
+ fn adjacency_table ( & self ) -> & HashMap < & ' a T , Vec < ( & ' a T , i32 ) > > ;
68
74
69
- fn add_node ( & mut self , node : & str ) -> bool {
70
- match self . adjacency_table ( ) . get ( node) {
71
- None => {
72
- self . adjacency_table_mutable ( )
73
- . insert ( ( * node) . to_string ( ) , Vec :: new ( ) ) ;
74
- true
75
- }
76
- _ => false ,
75
+ fn add_node ( & mut self , node : & ' a T ) -> bool {
76
+ if let Vacant ( entry) = self . adjacency_table_mutable ( ) . entry ( node) {
77
+ entry. insert ( Vec :: new ( ) ) ;
78
+ true
79
+ } else {
80
+ false
77
81
}
78
82
}
79
83
80
- fn add_edge ( & mut self , edge : ( & str , & str , i32 ) ) {
84
+ fn add_edge ( & mut self , edge : ( & ' a T , & ' a T , i32 ) ) {
81
85
self . add_node ( edge. 0 ) ;
82
86
self . add_node ( edge. 1 ) ;
83
87
84
88
self . adjacency_table_mutable ( )
85
- . entry ( edge. 0 . to_string ( ) )
89
+ . entry ( edge. 0 )
86
90
. and_modify ( |e| {
87
- e. push ( ( edge. 1 . to_string ( ) , edge. 2 ) ) ;
91
+ e. push ( ( edge. 1 , edge. 2 ) ) ;
88
92
} ) ;
89
93
}
90
94
91
- fn neighbours ( & self , node : & str ) -> Result < & Vec < ( String , i32 ) > , NodeNotInGraph > {
95
+ fn neighbours ( & self , node : & ' a T ) -> Result < & Vec < ( & ' a T , i32 ) > , NodeNotInGraph > {
92
96
match self . adjacency_table ( ) . get ( node) {
93
97
None => Err ( NodeNotInGraph ) ,
94
98
Some ( i) => Ok ( i) ,
95
99
}
96
100
}
97
101
98
- fn contains ( & self , node : & str ) -> bool {
102
+ fn contains ( & self , node : & ' a T ) -> bool {
99
103
self . adjacency_table ( ) . get ( node) . is_some ( )
100
104
}
101
105
102
- fn nodes ( & self ) -> HashSet < & String > {
103
- self . adjacency_table ( ) . keys ( ) . collect ( )
106
+ fn nodes ( & self ) -> HashSet < & ' a T > {
107
+ self . adjacency_table ( ) . keys ( ) . copied ( ) . collect ( )
104
108
}
105
109
106
- fn edges ( & self ) -> Vec < ( & String , & String , i32 ) > {
107
- let mut edges = Vec :: new ( ) ;
108
- for ( from_node, from_node_neighbours) in self . adjacency_table ( ) {
109
- for ( to_node, weight) in from_node_neighbours {
110
- edges. push ( ( from_node, to_node, * weight) ) ;
111
- }
112
- }
113
- edges
110
+ fn edges ( & self ) -> Vec < ( & ' a T , & ' a T , i32 ) > {
111
+ self . adjacency_table ( )
112
+ . iter ( )
113
+ . flat_map ( |( from_node, from_node_neighbours) | {
114
+ from_node_neighbours
115
+ . iter ( )
116
+ . map ( move |( to_node, weight) | ( * from_node, * to_node, * weight) )
117
+ } )
118
+ . collect ( )
114
119
}
115
120
}
116
121
117
122
#[ cfg( test) ]
118
123
mod test_undirected_graph {
119
124
use super :: Graph ;
120
125
use super :: UndirectedGraph ;
126
+
121
127
#[ test]
122
128
fn test_add_edge ( ) {
123
- let mut graph = UndirectedGraph :: new ( ) ;
129
+ let mut graph: UndirectedGraph < String > = UndirectedGraph :: new ( ) ;
124
130
125
- graph. add_edge ( ( "a" , "b" , 5 ) ) ;
126
- graph. add_edge ( ( "b" , "c" , 10 ) ) ;
127
- graph. add_edge ( ( "c" , "a" , 7 ) ) ;
131
+ let a = String :: from ( "a" ) ;
132
+ let b = String :: from ( "b" ) ;
133
+ let c = String :: from ( "c" ) ;
134
+
135
+ graph. add_edge ( ( & a, & b, 5 ) ) ;
136
+ graph. add_edge ( ( & b, & c, 10 ) ) ;
137
+ graph. add_edge ( ( & c, & a, 7 ) ) ;
128
138
129
139
let expected_edges = [
130
- ( & String :: from ( "a" ) , & String :: from ( "b" ) , 5 ) ,
131
- ( & String :: from ( "b" ) , & String :: from ( "a" ) , 5 ) ,
132
- ( & String :: from ( "c" ) , & String :: from ( "a" ) , 7 ) ,
133
- ( & String :: from ( "a" ) , & String :: from ( "c" ) , 7 ) ,
134
- ( & String :: from ( "b" ) , & String :: from ( "c" ) , 10 ) ,
135
- ( & String :: from ( "c" ) , & String :: from ( "b" ) , 10 ) ,
140
+ ( & a , & b , 5 ) ,
141
+ ( & b , & a , 5 ) ,
142
+ ( & c , & a , 7 ) ,
143
+ ( & a , & c , 7 ) ,
144
+ ( & b , & c , 10 ) ,
145
+ ( & c , & b , 10 ) ,
136
146
] ;
137
147
for edge in expected_edges. iter ( ) {
138
- assert_eq ! ( graph. edges( ) . contains( edge) , true ) ;
148
+ assert ! ( graph. edges( ) . contains( edge) ) ;
139
149
}
140
150
}
141
151
142
152
#[ test]
143
153
fn test_neighbours ( ) {
144
- let mut graph = UndirectedGraph :: new ( ) ;
154
+ let mut graph: UndirectedGraph < String > = UndirectedGraph :: new ( ) ;
155
+
156
+ let a = String :: from ( "a" ) ;
157
+ let b = String :: from ( "b" ) ;
158
+ let c = String :: from ( "c" ) ;
145
159
146
- graph. add_edge ( ( "a" , "b" , 5 ) ) ;
147
- graph. add_edge ( ( "b" , "c" , 10 ) ) ;
148
- graph. add_edge ( ( "c" , "a" , 7 ) ) ;
160
+ graph. add_edge ( ( & a , & b , 5 ) ) ;
161
+ graph. add_edge ( ( & b , & c , 10 ) ) ;
162
+ graph. add_edge ( ( & c , & a , 7 ) ) ;
149
163
150
- assert_eq ! (
151
- graph. neighbours( "a" ) . unwrap( ) ,
152
- & vec![ ( String :: from( "b" ) , 5 ) , ( String :: from( "c" ) , 7 ) ]
153
- ) ;
164
+ assert_eq ! ( graph. neighbours( & a) . unwrap( ) , & vec![ ( & b, 5 ) , ( & c, 7 ) ] ) ;
154
165
}
155
166
}
156
167
@@ -161,60 +172,98 @@ mod test_directed_graph {
161
172
162
173
#[ test]
163
174
fn test_add_node ( ) {
164
- let mut graph = DirectedGraph :: new ( ) ;
165
- graph. add_node ( "a" ) ;
166
- graph. add_node ( "b" ) ;
167
- graph. add_node ( "c" ) ;
168
- assert_eq ! (
169
- graph. nodes( ) ,
170
- [ & String :: from( "a" ) , & String :: from( "b" ) , & String :: from( "c" ) ]
171
- . iter( )
172
- . cloned( )
173
- . collect( )
174
- ) ;
175
+ let mut graph: DirectedGraph < String > = DirectedGraph :: new ( ) ;
176
+
177
+ let a = String :: from ( "a" ) ;
178
+ let b = String :: from ( "b" ) ;
179
+ let c = String :: from ( "c" ) ;
180
+
181
+ graph. add_node ( & a) ;
182
+ graph. add_node ( & b) ;
183
+ graph. add_node ( & c) ;
184
+
185
+ assert_eq ! ( graph. nodes( ) , [ & a, & b, & c] . iter( ) . cloned( ) . collect( ) ) ;
186
+ }
187
+
188
+ #[ test]
189
+ fn test_add_node_with_struct ( ) {
190
+ #[ derive( PartialEq , Eq , Hash , Debug ) ]
191
+ struct Node {
192
+ name : String ,
193
+ value : i32 ,
194
+ }
195
+
196
+ let mut graph: DirectedGraph < Node > = DirectedGraph :: new ( ) ;
197
+
198
+ let a = Node {
199
+ name : String :: from ( "a" ) ,
200
+ value : 1 ,
201
+ } ;
202
+ let b = Node {
203
+ name : String :: from ( "b" ) ,
204
+ value : 2 ,
205
+ } ;
206
+ let c = Node {
207
+ name : String :: from ( "c" ) ,
208
+ value : 3 ,
209
+ } ;
210
+
211
+ graph. add_node ( & a) ;
212
+ graph. add_node ( & b) ;
213
+ graph. add_node ( & c) ;
214
+
215
+ assert_eq ! ( graph. nodes( ) , [ & a, & b, & c] . iter( ) . cloned( ) . collect( ) ) ;
175
216
}
176
217
177
218
#[ test]
178
219
fn test_add_edge ( ) {
179
- let mut graph = DirectedGraph :: new ( ) ;
220
+ let mut graph: DirectedGraph < String > = DirectedGraph :: new ( ) ;
180
221
181
- graph . add_edge ( ( "a" , "b" , 5 ) ) ;
182
- graph . add_edge ( ( "c" , "a" , 7 ) ) ;
183
- graph . add_edge ( ( "b" , "c" , 10 ) ) ;
222
+ let a = String :: from ( "a" ) ;
223
+ let b = String :: from ( "b" ) ;
224
+ let c = String :: from ( "c" ) ;
184
225
185
- let expected_edges = [
186
- ( & String :: from ( "a" ) , & String :: from ( "b" ) , 5 ) ,
187
- ( & String :: from ( "c" ) , & String :: from ( "a" ) , 7 ) ,
188
- ( & String :: from ( "b" ) , & String :: from ( "c" ) , 10 ) ,
189
- ] ;
226
+ graph . add_edge ( ( & a , & b , 5 ) ) ;
227
+ graph . add_edge ( ( & c , & a , 7 ) ) ;
228
+ graph . add_edge ( ( & b , & c , 10 ) ) ;
229
+
230
+ let expected_edges = [ ( & a , & b , 5 ) , ( & c , & a , 7 ) , ( & b , & c , 10 ) ] ;
190
231
for edge in expected_edges. iter ( ) {
191
- assert_eq ! ( graph. edges( ) . contains( edge) , true ) ;
232
+ assert ! ( graph. edges( ) . contains( edge) ) ;
192
233
}
193
234
}
194
235
195
236
#[ test]
196
237
fn test_neighbours ( ) {
197
- let mut graph = DirectedGraph :: new ( ) ;
238
+ let mut graph: DirectedGraph < String > = DirectedGraph :: new ( ) ;
239
+
240
+ let a = String :: from ( "a" ) ;
241
+ let b = String :: from ( "b" ) ;
242
+ let c = String :: from ( "c" ) ;
198
243
199
- graph. add_edge ( ( "a" , "b" , 5 ) ) ;
200
- graph. add_edge ( ( "b" , "c" , 10 ) ) ;
201
- graph. add_edge ( ( "c" , "a" , 7 ) ) ;
244
+ graph. add_edge ( ( & a , & b , 5 ) ) ;
245
+ graph. add_edge ( ( & b , & c , 10 ) ) ;
246
+ graph. add_edge ( ( & c , & a , 7 ) ) ;
202
247
203
- assert_eq ! (
204
- graph. neighbours( "a" ) . unwrap( ) ,
205
- & vec![ ( String :: from( "b" ) , 5 ) ]
206
- ) ;
248
+ assert_eq ! ( graph. neighbours( & a) . unwrap( ) , & vec![ ( & b, 5 ) ] ) ;
207
249
}
208
250
209
251
#[ test]
210
252
fn test_contains ( ) {
211
- let mut graph = DirectedGraph :: new ( ) ;
212
- graph. add_node ( "a" ) ;
213
- graph. add_node ( "b" ) ;
214
- graph. add_node ( "c" ) ;
215
- assert_eq ! ( graph. contains( "a" ) , true ) ;
216
- assert_eq ! ( graph. contains( "b" ) , true ) ;
217
- assert_eq ! ( graph. contains( "c" ) , true ) ;
218
- assert_eq ! ( graph. contains( "d" ) , false ) ;
253
+ let mut graph: DirectedGraph < String > = DirectedGraph :: new ( ) ;
254
+
255
+ let a = String :: from ( "a" ) ;
256
+ let b = String :: from ( "b" ) ;
257
+ let c = String :: from ( "c" ) ;
258
+ let d = String :: from ( "d" ) ;
259
+
260
+ graph. add_node ( & a) ;
261
+ graph. add_node ( & b) ;
262
+ graph. add_node ( & c) ;
263
+
264
+ assert ! ( graph. contains( & a) ) ;
265
+ assert ! ( graph. contains( & b) ) ;
266
+ assert ! ( graph. contains( & c) ) ;
267
+ assert ! ( !graph. contains( & d) ) ;
219
268
}
220
269
}
0 commit comments