@@ -33,7 +33,8 @@ pub enum GraphErr {
3333pub struct Graph < T > {
3434 vertices : HashMap < VertexId , ( T , VertexId ) > ,
3535 edges : HashMap < Edge , f32 > ,
36- roots : Vec < VertexId > ,
36+ roots : HashSet < VertexId > ,
37+ tips : HashSet < VertexId > ,
3738 inbound_table : HashMap < VertexId , Vec < VertexId > > ,
3839 outbound_table : HashMap < VertexId , Vec < VertexId > > ,
3940}
@@ -54,7 +55,8 @@ impl<T> Graph<T> {
5455 Graph {
5556 vertices : HashMap :: new ( ) ,
5657 edges : HashMap :: new ( ) ,
57- roots : Vec :: new ( ) ,
58+ roots : HashSet :: new ( ) ,
59+ tips : HashSet :: new ( ) ,
5860 inbound_table : HashMap :: new ( ) ,
5961 outbound_table : HashMap :: new ( ) ,
6062 }
@@ -69,10 +71,17 @@ impl<T> Graph<T> {
6971 /// let mut graph: Graph<usize> = Graph::with_capacity(5);
7072 /// ```
7173 pub fn with_capacity ( capacity : usize ) -> Graph < T > {
74+ let edges_capacity = if capacity < 100 {
75+ usize:: pow ( capacity, 2 )
76+ } else {
77+ capacity
78+ } ;
79+
7280 Graph {
7381 vertices : HashMap :: with_capacity ( capacity) ,
74- edges : HashMap :: with_capacity ( usize:: pow ( capacity, 2 ) ) ,
75- roots : Vec :: with_capacity ( capacity) ,
82+ edges : HashMap :: with_capacity ( edges_capacity) ,
83+ roots : HashSet :: with_capacity ( capacity) ,
84+ tips : HashSet :: with_capacity ( capacity) ,
7685 inbound_table : HashMap :: with_capacity ( capacity) ,
7786 outbound_table : HashMap :: with_capacity ( capacity) ,
7887 }
@@ -85,13 +94,14 @@ impl<T> Graph<T> {
8594 ///
8695 /// let mut graph: Graph<usize> = Graph::with_capacity(5);
8796 ///
88- /// assert_eq !(graph.capacity(), 5);
97+ /// assert !(graph.capacity() >= 5);
8998 /// ```
9099 pub fn capacity ( & self ) -> usize {
91100 min ! (
92101 self . vertices. capacity( ) ,
93102 self . edges. capacity( ) ,
94103 self . roots. capacity( ) ,
104+ self . tips. capacity( ) ,
95105 self . inbound_table. capacity( ) ,
96106 self . outbound_table. capacity( )
97107 )
@@ -121,12 +131,17 @@ impl<T> Graph<T> {
121131 // number of vertices that are currently placed
122132 // in the graph.
123133 let new_capacity = self . vertices . len ( ) + additional;
124- let edges_capacity = usize:: pow ( new_capacity, 2 ) ;
134+ let edges_capacity = if new_capacity < 100 {
135+ usize:: pow ( new_capacity, 2 )
136+ } else {
137+ new_capacity
138+ } ;
125139 let edges_count = self . edges . len ( ) ;
126140 let edges_additional = edges_capacity - edges_count;
127141
128142 self . edges . reserve ( edges_additional) ;
129143 self . roots . reserve ( additional) ;
144+ self . tips . reserve ( additional) ;
130145 self . vertices . reserve ( additional) ;
131146 self . outbound_table . reserve ( additional) ;
132147 self . inbound_table . reserve ( additional) ;
@@ -142,14 +157,15 @@ impl<T> Graph<T> {
142157 ///
143158 /// let mut graph: Graph<usize> = Graph::with_capacity(5);
144159 ///
145- /// assert_eq !(graph.capacity(), 5);
160+ /// assert !(graph.capacity() >= 5);
146161 ///
147162 /// graph.shrink_to_fit();
148- /// assert_eq !(graph.capacity(), 0 );
163+ /// assert !(graph.capacity() < 5 );
149164 /// ```
150165 pub fn shrink_to_fit ( & mut self ) {
151166 self . edges . shrink_to_fit ( ) ;
152167 self . roots . shrink_to_fit ( ) ;
168+ self . tips . shrink_to_fit ( ) ;
153169 self . vertices . shrink_to_fit ( ) ;
154170 self . outbound_table . shrink_to_fit ( ) ;
155171 self . inbound_table . shrink_to_fit ( ) ;
@@ -181,7 +197,8 @@ impl<T> Graph<T> {
181197 let id = VertexId :: random ( ) ;
182198
183199 self . vertices . insert ( id. clone ( ) , ( item, id. clone ( ) ) ) ;
184- self . roots . push ( id) ;
200+ self . roots . insert ( id) ;
201+ self . tips . insert ( id) ;
185202
186203 id
187204 }
@@ -468,18 +485,35 @@ impl<T> Graph<T> {
468485 /// ```
469486 pub fn remove ( & mut self , id : & VertexId ) {
470487 self . vertices . remove ( id) ;
471- self . inbound_table . remove ( id) ;
472488
473- // Mark outbounds as roots if they have no inbounds.
474- for ( n, _) in self . outbound_table . iter ( ) {
475- if self . in_neighbors_count ( n) == 0 {
476- self . roots . push ( n. clone ( ) ) ;
489+ // Remove each inbound edge
490+ if let Some ( inbounds) = self . inbound_table . remove ( id) {
491+ for vertex in inbounds {
492+ self . remove_edge ( & vertex, id) ;
493+
494+ // Add to tips if inbound vertex doesn't
495+ // have other outbound vertices.
496+ if self . out_neighbors_count ( & vertex) == 0 {
497+ self . tips . insert ( vertex) ;
498+ }
499+ }
500+ }
501+
502+ // Remove each outbound edge
503+ if let Some ( outbounds) = self . outbound_table . remove ( id) {
504+ for vertex in outbounds {
505+ self . remove_edge ( id, & vertex) ;
506+
507+ // Add to roots if outbound vertex doesn't
508+ // have other inbound vertices.
509+ if self . in_neighbors_count ( & vertex) == 0 {
510+ self . roots . insert ( vertex) ;
511+ }
477512 }
478513 }
479514
480- self . outbound_table . remove ( id) ;
481- self . edges . retain ( |e, _| !e. matches_any ( id) ) ;
482- self . roots . retain ( |r| r != id) ;
515+ self . roots . remove ( & id) ;
516+ self . tips . remove ( & id) ;
483517 }
484518
485519 /// Removes the specified edge from the graph.
@@ -509,22 +543,22 @@ impl<T> Graph<T> {
509543 /// assert_eq!(graph.edge_count(), 2);
510544 /// ```
511545 pub fn remove_edge ( & mut self , a : & VertexId , b : & VertexId ) {
512- let mut remove = false ;
513-
514546 if let Some ( outbounds) = self . outbound_table . get_mut ( a) {
515547 outbounds. retain ( |v| v != b) ;
516- remove = true ;
517548 }
518549
519550 // If outbound vertex doesn't have any more inbounds,
520551 // mark it as root.
521552 if self . in_neighbors_count ( & b) == 0 {
522- self . roots . push ( b. clone ( ) ) ;
553+ self . roots . insert ( b. clone ( ) ) ;
523554 }
524555
525- if remove {
526- self . edges . retain ( |e, _| !e. matches ( a, b) ) ;
556+ // Mark vertex as tip if it doesn't have any more outbounds.
557+ if self . out_neighbors_count ( & a) == 0 {
558+ self . tips . insert ( a. clone ( ) ) ;
527559 }
560+
561+ self . edges . remove ( & Edge :: new ( a. clone ( ) , b. clone ( ) ) ) ;
528562 }
529563
530564 /// Iterates through the graph and only keeps
@@ -547,14 +581,12 @@ impl<T> Graph<T> {
547581 /// assert_eq!(graph.vertex_count(), 2);
548582 /// ```
549583 pub fn retain ( & mut self , fun : impl Fn ( & T ) -> bool ) {
550- let vertices: Vec < VertexId > = self . vertices ( ) . cloned ( ) . collect ( ) ;
551- let vertices: Vec < VertexId > = vertices
552- . iter ( )
584+ let vertices: Vec < VertexId > = self . vertices ( )
553585 . filter ( |v| !fun ( self . fetch ( v) . unwrap ( ) ) )
554586 . cloned ( )
555587 . collect ( ) ;
556-
557- vertices. iter ( ) . for_each ( |v| self . remove ( v) ) ;
588+
589+ vertices. iter ( ) . for_each ( |v| self . remove ( & v) ) ;
558590 }
559591
560592 /// Performs a fold over the vertices that are
@@ -879,6 +911,39 @@ impl<T> Graph<T> {
879911 VertexIter ( Box :: new ( self . roots . iter ( ) . map ( AsRef :: as_ref) ) )
880912 }
881913
914+ /// Returns an iterator over the tips of the graph. These
915+ /// are all the vertices that have an inbound edge but no
916+ /// outbound edge.
917+ ///
918+ /// ## Example
919+ /// ```rust
920+ /// use graphlib::Graph;
921+ ///
922+ /// let mut graph: Graph<usize> = Graph::new();
923+ /// let mut tips = vec![];
924+ ///
925+ /// let v1 = graph.add_vertex(0);
926+ /// let v2 = graph.add_vertex(1);
927+ /// let v3 = graph.add_vertex(2);
928+ /// let v4 = graph.add_vertex(3);
929+ ///
930+ /// graph.add_edge(&v1, &v2).unwrap();
931+ /// graph.add_edge(&v3, &v1).unwrap();
932+ /// graph.add_edge(&v1, &v4).unwrap();
933+ ///
934+ /// // Iterate over tips
935+ /// for v in graph.tips() {
936+ /// tips.push(v);
937+ /// }
938+ ///
939+ /// assert_eq!(tips.len(), 2);
940+ /// assert_eq!(tips[0], &v2);
941+ /// assert_eq!(tips[1], &v4);
942+ /// ```
943+ pub fn tips ( & self ) -> VertexIter < ' _ > {
944+ VertexIter ( Box :: new ( self . tips . iter ( ) . map ( AsRef :: as_ref) ) )
945+ }
946+
882947 /// Returns an iterator over all of the
883948 /// vertices that are placed in the graph.
884949 ///
@@ -1059,7 +1124,10 @@ impl<T> Graph<T> {
10591124 }
10601125
10611126 // Remove outbound vertex from roots
1062- self . roots = self . roots . iter ( ) . filter ( |v| * v != b) . cloned ( ) . collect ( ) ;
1127+ self . roots . remove ( & b) ;
1128+
1129+ // Remove inbound vertex from tips
1130+ self . tips . remove ( & a) ;
10631131
10641132 Ok ( ( ) )
10651133 }
0 commit comments