I’m having some trouble with implementing a breadth-first search in my program that tries to find a Kevin Bacon number. I have created a temporary hashset that stores visited nodes, but the program keeps revisiting nodes despite my removing the nodes from the list that I feed back into the queue.
The information for actors and movies is stored in a HashMap(String, HashSet(String)) – so if you put in an actor as a key, you get the movies they acted in, and if you put in a movie as the key, you get the actors that have acted in it. Attached below is my code and what the System.out.prints print. Thanks for the help!
public List<String> findBaconPath (String actor) throws IllegalArgumentException {
ArrayList<String> list = new ArrayList<String>();
HashSet<String> visited = new HashSet<String>();
visited.add(actor);
LinkedList<String> bfs = new LinkedList<String>();
bfs.add(actor);
while (!bfs.isEmpty()){
String curr = bfs.remove(); //The current actor we are looking at.
visited.add(curr);
HashSet<String> mov = myMovies.get(curr);
Iterator<String> it = mov.iterator();
while (it.hasNext()){
String next = it.next(); //The next movie in the iterator.
visited.add(next);
HashSet<String> coStars = myMovies.get(next);
coStars.removeAll(visited);
if (coStars.contains("Bacon, Kevin")){
list.add(curr);
list.add(next);
list.add("Bacon, Kevin");
System.out.println(list.toString());
return list;
}
else {
list.add(curr);
list.add(next);
System.out.println("This is what is in visited: "+visited.toString());
System.out.println("This is what is in coStars pre removal. "+ coStars.toString());
coStars.removeAll(visited);
System.out.println("This is what is in coStars post removal. "+ coStars.toString());
Iterator<String> cos = coStars.iterator();
while (cos.hasNext()){
bfs.add(cos.next());
}
}
}
}
return list;
}
- This is what is in visited: [D, Movie 7]
- This is what is in coStars pre removal. [D, A, B, C]
- This is what is in coStars post removal. [A, B, C]
- This is what is in visited: [D, Movie 7, Movie 2]
- This is what is in coStars pre removal. [D, E, A, B]
- This is what is in coStars post removal. [E, A, B]
- This is what is in visited: [D, A, Movie 7, Movie 2]
- This is what is in coStars pre removal. [A, B, C]
- This is what is in coStars post removal. [B, C]
- This is what is in visited: [D, A, Movie 7, Movie 2]
- This is what is in coStars pre removal. [E, A, B]
- This is what is in coStars post removal. [E, B]
- This is what is in visited: [D, A, Movie 7, Movie 2, Movie 1]
- This is what is in coStars pre removal. [A, B, C]
- This is what is in coStars post removal. [B, C]
- [D, Movie 7, D, Movie 2, A, Movie 7, A, Movie 2, A, Movie 1, A, Movie 0, Bacon, Kevin]
It might help if you better distinguish movies and actors in your visited list instead of mixing them. Something like:
Then when you do removeAll you can always identify the entry in “visited” by movie title.
Also, removeAll is getting called twice per loop. Once just before ‘if (coStars.contains(“Bacon, Kevin”)){‘ and once again just before you print ‘post removal.’
Btw, is this the answer? Movie 7, Movie 2, Movie 1, Movie 0