有向无环图
作者:互联网
有向无环图
有向图是由顶点
和有向边
组成的,有向边由上游点和下游点组成,比如(u,v)表示一个有向边,其中u就是该有向边的上游点,v就是该有向边的下游点,入度
是指一个顶点作为下游点所在有向边的个数,比如下图中,顶点1的入度是0,顶点3的入度是1,顶点6的入度是2,出度
是指一个顶点作为上游点所在有向边的个数,比如顶点1的出度是1,顶点3的出度是2.有向无环图就是不存在环形的有向图,即不存在任何一个从某个顶点出发,经过一条或者多条边后,重新又回到了出发点的路径。
有向图的拓扑排序
是指这样一个线性序列:如果(u,v)是有向无环图中的一条边,那么在线性序列中,u必须出现在v之前。利用拓扑排序所产生的线性序列不一定是唯一的。比如下图的拓扑顺序可以是:9->10->2->1->3->5->4->6->11->12->7->8->13->14
,也可以是1->3->2->4->5->6->9->10->11->12->7->8->13->14
.
那么如何给出一个有向无环的拓扑排序?
伪代码如下:
输入:G:一个顶点编号为从1~n的有向无环图;
输出:关于该图的一个拓扑序列;
步骤:
1.构造一个入度数组,in-degree,根据G,填充该入度数组;
2.将入度数组中的每个入度值为0的顶点,压入next栈;
3.只要next不为空,执行如下操作:
A.从next中弹出一个顶点u
B.将u添加到线性序列的末尾处
C.对于每个与u邻接的下游点v:
i.令in-dgree[v]的值自减1
ii. 如果in-degree[v]=0,将v压入next栈中
4.返回线性序列
该伪代码的核心思想就是移除入度为0的顶点,以及其所在的有向边,与该点邻接的下游点的入度均减一,那么剩下的图仍然是有向无环图,反复操作,就得到了线性序列。比如下图,移除1后,3就变成了入度值为0的顶点,故再移除3,同理,移除5,到了6,但是6的入度值此时为1,不为0,所以可以再移除2,移除4...等等。
class Program
{
public static void Main()
{
var a = new Dictionary<int, List<int>> { [0] = new List<int> { 1 } };
var graph = new Dictionary<int, List<int>>
{
[1] = new List<int>{ 3 },[2] = new List<int>{4},[3] = new List<int>{4,5},
[4] = new List<int>{ 6 },[5] = new List<int>{ 6 },
[6] = new List<int>{ 7, 11 },
[7] = new List<int>{ 8 },[8] = new List<int>{13},
[9] = new List<int>{ 10 },
[10] = new List<int>{ 11 }, [11] = new List<int>{ 12 },
[12] = new List<int>{ 13 },
[13] = new List<int>{14},[14]=new List<int>()
};
var result = TopoloGicalSort(graph);
foreach (var re in result)
Console.Write(re + "->");
}
/// <summary>
/// 用字典的形式来表示有向无环形图
/// 其中键是每个顶点,值是该顶点传向的顶点
/// </summary>
/// <param name="graph"></param>
public static List<int> TopoloGicalSort(Dictionary<int,List<int>>graph)
{
var result = new List<int>();
var inDegree = new Dictionary<int, int>();
//填充inDegree入度数组
foreach(var kv in graph)
{
if (!inDegree.ContainsKey(kv.Key))
{
inDegree.Add(kv.Key, 0);
}
foreach(var verteice in kv.Value)
{
if (!inDegree.ContainsKey(verteice))
{
inDegree.Add(verteice, 1);
}
else
{
inDegree[verteice] += 1;
}
}
}
var next = new Stack<int>();//存放所有入度为0的顶点的栈
//next初始化
foreach(var kv in inDegree)
{
if (kv.Value == 0)
{
next.Push(kv.Key);
}
}
while (next.Count != 0)
{
var verticeTemp = next.Pop();
result.Add(verticeTemp);
foreach (var vertice in graph[verticeTemp])
{
inDegree[vertice] -= 1;
if (inDegree[vertice] == 0)
next.Push(vertice);
}
}
return result;
}
}
标签:inDegree,入度,List,环图,new,var,顶点 来源: https://www.cnblogs.com/johnyang/p/15757406.html