zoukankan      html  css  js  c++  java
  • 有向无环图

    有向无环图

    有向图是由顶点有向边组成的,有向边由上游点和下游点组成,比如(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;
            }
        }
    

    ##### 愿你一寸一寸地攻城略地,一点一点地焕然一新 #####
  • 相关阅读:
    JavaScript数据结构——模仿ES6中定义的类似的Set类
    webpack简单的项目配置发生的错误
    三国
    把握中国经济的大局与动力
    人生道路
    C++
    https://计算机等级分类总结
    https://计算机四级
    https://计算机三级
    https://计算机二级
  • 原文地址:https://www.cnblogs.com/johnyang/p/15757406.html
Copyright © 2011-2022 走看看