Reputation: 2185
I have a object, let's call it "Friend".
This object has method "GetFriendsOfFriend", that returns a List<Friend>
.
Given a user input of say 5, all of the Friends friends and the friends friends friends (you get the point) down in a level of 5 (this can be up to 20).
This may be a lot of calculations, so I don't know if recursion is the best solution.
Does anyone have a smart idea of 1. How to do this recursive function best? 2. How to do it without recursion.
Thanks!
Upvotes: 0
Views: 5540
Reputation: 10565
Here is a non recursive version of this code:
public static void ProcessFriendsOf(string person) {
var toVisit = new Queue<string>();
var seen = new HashSet<string>();
toVisit.Enqueue(person);
seen.Add(person);
while(toVisit.Count > 0) {
var current = toVisit.Dequeue();
//process this friend in some way
foreach(var friend in GetFriendsOfFriend(current)) {
if (!seen.Contains(friend)) {
toVisit.Enqueue(friend);
seen.Add(friend);
}
}
}
}
It avoids infinite loop by keeping a HashSet of all members already seen and not adding a member to be processed more than once.
It visits friends using a Queue, in a way that is known as Breadth-first search. If we use a Stack instead of a Queue, it becomes a Depth-first search, and would behave pretty much the same as a recursive approach (which uses an implicit stack - the call stack).
Upvotes: 1
Reputation: 38825
Whilst is is certainly possible to do this without recursion, I don't see a particular problem with what you're trying to do. To prevent things going crazy, it might make sense to set a maximum to prevent your program from dying.
public class Friend
{
public static readonly int MaxDepth = 8; // prevent more than 8 recursions
private List<Friend> myFriends_ = new List<Friend>();
// private implementation
private void InternalFriends(int depth, int currDepth, List<Friend> list)
{
// Add "us"
if(currDepth > 1 && !list.Contains(this))
list.Add(this);
if(currDepth <= depth)
{
foreach(Friend f in myFriends_)
{
if(!list.Contains(f))
f.InternalFriends(depth, depth + 1, list); // we can all private functions here.
}
}
} // eo InternalFriends
public List<Friend> GetFriendsOfFriend(int depth)
{
List<Friend> ret = new List<Friend>();
InternalFriends(depth < MaxDepth ? depth : MaxDepth, 1, ret);
return ret;
} // eo getFriendsOfFriend
} // eo class Friend
EDIT: Fixed an error in the code in that an actual friend would not get added, just "their" friends. This is only necessary when adding friends after a depth of "1" (the first call). I also made use of Contains
to check for duplicates.
Upvotes: 4