, - " - , ". , node , , . , DFS- , , DFS .
node , node:
static string FindCycleHelper(string start, Dictionary<string, string> successors, HashSet<string> stackVisited)
{
string current = start;
while (current != null)
{
if (stackVisited.Contains(current))
{
return current;
}
stackVisited.Add(current);
successors.TryGetValue(current, out current);
}
return null;
}
, , node ( previouslyVisited
):
static string FindCycleHelper(string start, Dictionary<string, string> successors, HashSet<string> stackVisited, HashSet<string> previouslyVisited)
{
string current = start;
while (current != null)
{
if (previouslyVisited.Contains(current))
{
return null;
}
if (stackVisited.Contains(current))
{
return current;
}
stackVisited.Add(current);
successors.TryGetValue(current, out current);
}
return null;
}
static string FindCycle(string start, Dictionary<string, string> successors, HashSet<string> globalVisited)
{
HashSet<string> stackVisited = new HashSet<string>();
var result = FindCycleHelper(start, successors, stackVisited, globalVisited);
globalVisited.UnionWith(stackVisited);
return result;
}
old
node . , node, :
IEnumerable<Item> items = new Item[]
{
new Item{ Old = "a", Target = "b" },
new Item{ Old = "b", Target = "c" },
new Item{ Old = "c", Target = "d" },
new Item{ Old = "d", Target = "a" },
new Item{ Old = "j", Target = "x" },
new Item{ Old = "w", Target = "s" },
};
var successors = items.ToDictionary(x => x.Old, x => x.Target);
var visited = new HashSet<string>();
List<List<string>> cycles = new List<List<string>>();
foreach (var item in items)
{
string cycleStart = FindCycle(item.Old, successors, visited);
if (cycleStart != null)
{
List<string> cycle = GetCycleMembers(cycleStart, successors);
cycles.Add(cycle);
}
}
.
foreach (var cycle in cycles)
{
Console.WriteLine("Cycle:");
Console.WriteLine(string.Join(" # ", cycle));
Console.WriteLine();
}
GetCycleMembers
- node:
private static List<string> GetCycleMembers(string cycleStart, Dictionary<string, string> successors)
{
var visited = new HashSet<string>();
var members = new List<string>();
var current = cycleStart;
while (!visited.Contains(current))
{
members.Add(current);
visited.Add(current);
current = successors[current];
}
return members;
}