/**
 * Iterator is a behavioral design pattern that traverse
 * elements of a collection without exposing its underlying
 * representation. It extracts the traversal behavior of a
 * collection into a separate `Iterator` object.
 */ class BFSIterator < T > implements Iterator < T > { private queue : T [ ] = [ ] ; private visited : Set < T > = new Set ( ) ; private adjacencyList : Map < T , Set < T > > ; constructor ( adjacencyList ) { const vertex = Array . from ( adjacencyList . keys ( ) ) [ 0 ] ; this . queue . push ( vertex ) ; this . visited . add ( vertex ) ; this . adjacencyList = adjacencyList ; } next ( ) { const vertex = this . queue . shift ( ) ; if ( vertex === undefined ) { return { done : true , value : undefined , } ; } const neighbors = this . adjacencyList . get ( vertex ) ; if ( neighbors !== undefined ) { neighbors . forEach ( ( neighbor ) => { if ( this . visited . has ( neighbor ) ) { return ; } this . queue . push ( neighbor ) ; this . visited . add ( neighbor ) ; } ) ; } return { done : false , value : vertex , } ; } } class Graph < T > implements Iterable < T > { private adjacencyList : Map < T , Set < T > > = new Map ( ) ; addVertex ( value ) { this . adjacencyList . set ( value , new Set ( ) ) ; } addEdge ( vertex1 , vertex2 ) { const children1 = this . adjacencyList . get ( vertex1 ) ; const children2 = this . adjacencyList . get ( vertex1 ) ; if ( children1 && children2 ) { children1 . add ( vertex2 ) ; children2 . add ( vertex1 ) ; } } [ Symbol . iterator ] ( ) { return new BFSIterator ( this . adjacencyList ) ; } } export default Graph ;