Tarjan循环检测帮助C#
下面是tarjan循环检测的C#实现 算法如下所示:Tarjan循环检测帮助C#,c#,algorithm,cycle,directed-graph,tarjans-algorithm,C#,Algorithm,Cycle,Directed Graph,Tarjans Algorithm,下面是tarjan循环检测的C#实现 算法如下所示: 公共类TarjanCycleDetect { 私有静态列表强连接组件; 私有静态堆栈; 私有静态int索引; 私有静态数据包; 公共静态列表检测周期(DepGraph) { StronglyConnectedComponents=新列表(); 指数=0; S=新堆栈(); dg=g; foreach(g.顶点中的顶点v) { 如果(v.指数x.Key) .Where(x=>x.Count()>1) .Select(x=>x.ToList()
公共类TarjanCycleDetect
{
私有静态列表强连接组件;
私有静态堆栈;
私有静态int索引;
私有静态数据包;
公共静态列表检测周期(DepGraph)
{
StronglyConnectedComponents=新列表();
指数=0;
S=新堆栈();
dg=g;
foreach(g.顶点中的顶点v)
{
如果(v.指数<0)
{
strong连接(v);
}
}
返回强连接组件;
}
专用静态连接(顶点v)
{
v、 指数=指数;
v、 lowlink=指数;
索引++;
S.Push(v);
foreach(v.dependencies中的顶点w)
{
如果(w.指数<0)
{
strong连接(w);
v、 lowlink=数学最小值(v.lowlink,w.lowlink);
}
否则,如果(S.包含(w))
{
v、 lowlink=数学最小值(v.lowlink,w.index);
}
}
if(v.lowlink==v.index)
{
列表scc=新列表();
顶点w;
做
{
w=S.Pop();
新增专用条款(w);
}而(v!=w);
strong连接组件。添加(scc);
}
}
请注意,degraph只是一个顶点列表。顶点有一个表示边的其他顶点列表。此外,index和lowlink被初始化为-1
编辑:这是有效的…我只是误解了结果。上述事实是正确的,我不理解强连接组件是什么。我希望函数返回一个空的强连接组件列表,但它返回的是一个单节点列表
我相信上面的方法是有效的。如果需要,请随意使用!自2008年起,quickgraph已支持此算法。有关实现,请参阅
StronglyConnectedComponents算法
类,或AlgorithmExtensions.StronglyConnectedComponents
方法,了解使用快捷方式
例如:
// Initialize result dictionary
IDictionary<string, int> comps = new Dictionary<string, int>();
// Run the algorithm
graph.StronglyConnectedComponents(out comps);
// Group and filter the dictionary
var cycles = comps
.GroupBy(x => x.Value, x => x.Key)
.Where(x => x.Count() > 1)
.Select(x => x.ToList())
//初始化结果字典
IDictionary comps=新字典();
//运行算法
图.strong连接组件(外部组件);
//对字典进行分组和筛选
var周期=补偿
.GroupBy(x=>x.Value,x=>x.Key)
.Where(x=>x.Count()>1)
.Select(x=>x.ToList())
如果有人想快速使用上述示例,则该示例不起作用。另外请注意,它是基于堆栈的,如果您不给出最琐碎的图形,它将引爆堆栈。下面是一个单元测试的工作示例,该示例对Tarjan wikipedia页面上显示的图形进行建模:
public class Vertex
{
public int Id { get;set; }
public int Index { get; set; }
public int Lowlink { get; set; }
public HashSet<Vertex> Dependencies { get; set; }
public Vertex()
{
Id = -1;
Index = -1;
Lowlink = -1;
Dependencies = new HashSet<Vertex>();
}
public override string ToString()
{
return string.Format("Vertex Id {0}", Id);
}
public override int GetHashCode()
{
return Id;
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
Vertex other = obj as Vertex;
if (other == null)
return false;
return Id == other.Id;
}
}
public class TarjanCycleDetectStack
{
protected List<List<Vertex>> _StronglyConnectedComponents;
protected Stack<Vertex> _Stack;
protected int _Index;
public List<List<Vertex>> DetectCycle(List<Vertex> graph_nodes)
{
_StronglyConnectedComponents = new List<List<Vertex>>();
_Index = 0;
_Stack = new Stack<Vertex>();
foreach (Vertex v in graph_nodes)
{
if (v.Index < 0)
{
StronglyConnect(v);
}
}
return _StronglyConnectedComponents;
}
private void StronglyConnect(Vertex v)
{
v.Index = _Index;
v.Lowlink = _Index;
_Index++;
_Stack.Push(v);
foreach (Vertex w in v.Dependencies)
{
if (w.Index < 0)
{
StronglyConnect(w);
v.Lowlink = Math.Min(v.Lowlink, w.Lowlink);
}
else if (_Stack.Contains(w))
{
v.Lowlink = Math.Min(v.Lowlink, w.Index);
}
}
if (v.Lowlink == v.Index)
{
List<Vertex> cycle = new List<Vertex>();
Vertex w;
do
{
w = _Stack.Pop();
cycle.Add(w);
} while (v != w);
_StronglyConnectedComponents.Add(cycle);
}
}
}
[TestMethod()]
public void TarjanStackTest()
{
// tests simple model presented on https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
var graph_nodes = new List<Vertex>();
var v1 = new Vertex() { Id = 1 };
var v2 = new Vertex() { Id = 2 };
var v3 = new Vertex() { Id = 3 };
var v4 = new Vertex() { Id = 4 };
var v5 = new Vertex() { Id = 5 };
var v6 = new Vertex() { Id = 6 };
var v7 = new Vertex() { Id = 7 };
var v8 = new Vertex() { Id = 8 };
v1.Dependencies.Add(v2);
v2.Dependencies.Add(v3);
v3.Dependencies.Add(v1);
v4.Dependencies.Add(v3);
v4.Dependencies.Add(v5);
v5.Dependencies.Add(v4);
v5.Dependencies.Add(v6);
v6.Dependencies.Add(v3);
v6.Dependencies.Add(v7);
v7.Dependencies.Add(v6);
v8.Dependencies.Add(v7);
v8.Dependencies.Add(v5);
v8.Dependencies.Add(v8);
graph_nodes.Add(v1);
graph_nodes.Add(v2);
graph_nodes.Add(v3);
graph_nodes.Add(v4);
graph_nodes.Add(v5);
graph_nodes.Add(v6);
graph_nodes.Add(v7);
graph_nodes.Add(v8);
var tcd = new TarjanCycleDetectStack();
var cycle_list = tcd.DetectCycle(graph_nodes);
Assert.IsTrue(cycle_list.Count == 4);
}
公共类顶点
{
公共int Id{get;set;}
公共int索引{get;set;}
公共int低位链接{get;set;}
公共哈希集依赖项{get;set;}
公共顶点()
{
Id=-1;
指数=-1;
Lowlink=-1;
依赖项=新的HashSet();
}
公共重写字符串ToString()
{
返回string.Format(“顶点Id{0}”,Id);
}
公共覆盖int GetHashCode()
{
返回Id;
}
公共覆盖布尔等于(对象对象对象)
{
if(obj==null)
返回false;
顶点其他=obj作为顶点;
如果(其他==null)
返回false;
返回Id==other.Id;
}
}
公共类TarjanCycleDetectStack
{
受保护列表\u strong连接组件;
受保护堆栈(u堆栈);;
受保护的整数指数;
公共列表检测循环(列表图_节点)
{
_StronglyConnectedComponents=新列表();
_指数=0;
_堆栈=新堆栈();
foreach(图_节点中的顶点v)
{
如果(v.指数<0)
{
强连接(v);
}
}
返回_strong连接的组件;
}
私有void strong连接(顶点v)
{
v、 指数=_指数;
v、 Lowlink=_指数;
_索引++;
_栈推(v);
foreach(v.Dependencies中的顶点w)
{
如果(w.指数<0)
{
强连接(w);
v、 Lowlink=数学最小值(v.Lowlink,w.Lowlink);
}
else如果(_堆栈包含(w))
{
v、 Lowlink=数学最小值(v.Lowlink,w.Index);
}
}
if(v.Lowlink==v.Index)
{
列表周期=新列表();
顶点w;
做
{
w=_Stack.Pop();
循环。添加(w);
}而(v!=w);
_strong连接组件。添加(循环);
}
}
}
[TestMethod()]
公共无效测试()
{
//测试简单的模型https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
var graph_nodes=新列表();
var v1=新顶点(){Id=1};
var v2=新顶点(){Id=2};
var v3=新顶点(){Id=3};
var v4=新顶点(){Id=4};
var v5=新顶点(){Id=5};
var v6=新顶点(){Id=6};
var v7=新顶点(){Id=7};
var v8=新顶点(){Id=8};
v1.Dependencies.Add(v2);
v2.Dependencies.Add(v3);
v3.Dependencies.Add(v1);
v4.Dependencies.Add(v3);
v4.Dependencies.Add(v5);
v5.Dependencies.Add(v4);
v5.Dependencies.Add(v6);
v6.Dependencies.Add(v3);
v6.Dependencies.Add(v7);
v7.Dependencies.Add(v6);
v8.Dependencies.Add(v7);
v8.副驾驶
public class Vertex
{
public int Id { get;set; }
public int Index { get; set; }
public int Lowlink { get; set; }
public HashSet<Vertex> Dependencies { get; set; }
public Vertex()
{
Id = -1;
Index = -1;
Lowlink = -1;
Dependencies = new HashSet<Vertex>();
}
public override string ToString()
{
return string.Format("Vertex Id {0}", Id);
}
public override int GetHashCode()
{
return Id;
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
Vertex other = obj as Vertex;
if (other == null)
return false;
return Id == other.Id;
}
}
public class TarjanCycleDetectStack
{
protected List<List<Vertex>> _StronglyConnectedComponents;
protected Stack<Vertex> _Stack;
protected int _Index;
public List<List<Vertex>> DetectCycle(List<Vertex> graph_nodes)
{
_StronglyConnectedComponents = new List<List<Vertex>>();
_Index = 0;
_Stack = new Stack<Vertex>();
foreach (Vertex v in graph_nodes)
{
if (v.Index < 0)
{
StronglyConnect(v);
}
}
return _StronglyConnectedComponents;
}
private void StronglyConnect(Vertex v)
{
v.Index = _Index;
v.Lowlink = _Index;
_Index++;
_Stack.Push(v);
foreach (Vertex w in v.Dependencies)
{
if (w.Index < 0)
{
StronglyConnect(w);
v.Lowlink = Math.Min(v.Lowlink, w.Lowlink);
}
else if (_Stack.Contains(w))
{
v.Lowlink = Math.Min(v.Lowlink, w.Index);
}
}
if (v.Lowlink == v.Index)
{
List<Vertex> cycle = new List<Vertex>();
Vertex w;
do
{
w = _Stack.Pop();
cycle.Add(w);
} while (v != w);
_StronglyConnectedComponents.Add(cycle);
}
}
}
[TestMethod()]
public void TarjanStackTest()
{
// tests simple model presented on https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
var graph_nodes = new List<Vertex>();
var v1 = new Vertex() { Id = 1 };
var v2 = new Vertex() { Id = 2 };
var v3 = new Vertex() { Id = 3 };
var v4 = new Vertex() { Id = 4 };
var v5 = new Vertex() { Id = 5 };
var v6 = new Vertex() { Id = 6 };
var v7 = new Vertex() { Id = 7 };
var v8 = new Vertex() { Id = 8 };
v1.Dependencies.Add(v2);
v2.Dependencies.Add(v3);
v3.Dependencies.Add(v1);
v4.Dependencies.Add(v3);
v4.Dependencies.Add(v5);
v5.Dependencies.Add(v4);
v5.Dependencies.Add(v6);
v6.Dependencies.Add(v3);
v6.Dependencies.Add(v7);
v7.Dependencies.Add(v6);
v8.Dependencies.Add(v7);
v8.Dependencies.Add(v5);
v8.Dependencies.Add(v8);
graph_nodes.Add(v1);
graph_nodes.Add(v2);
graph_nodes.Add(v3);
graph_nodes.Add(v4);
graph_nodes.Add(v5);
graph_nodes.Add(v6);
graph_nodes.Add(v7);
graph_nodes.Add(v8);
var tcd = new TarjanCycleDetectStack();
var cycle_list = tcd.DetectCycle(graph_nodes);
Assert.IsTrue(cycle_list.Count == 4);
}