C# 判断有向图是否存在环

代码实现

Program.cs

using System;

namespace Csharp_test
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            MyList mylist = new MyList();
            mylist.addNode("a");
            mylist.addNode("b");
            mylist.addNode("c");
            mylist.addNode("d");
            mylist.addNode("e");
            mylist.addEdge("a", new string[] {"b","c"});
            mylist.addEdge("b", new string[] {"c" });
            mylist.addEdge("c", new string[] {"d" });
            mylist.addEdge("d", new string[] {"e" });
            mylist.addEdge("e", new string[] {"a" });
            bool flag = mylist.topologicalSort();
            Console.WriteLine(flag ? "无环" : "有环");
        }
    }
}

MyList.cs

using System.Collections.Generic;

namespace Csharp_test
{
    class MyList
    {
        /// <summary>
        /// 顶点字符串名称-编号字典
        /// </summary>
        private Dictionary<string, int> noteIntDictionary = new Dictionary<string, int>();
        private Dictionary<int, string> noteStringDictionary = new Dictionary<int, string>();
        private static int[] emptyIntArray = { }; // 空Int数组
        private int cnt = 0;    // 顶点编号

        /// <summary>
        /// 顶点入度数
        /// </summary>
        private List<int> inDegree = new List<int>();

        /// <summary>
        /// 顶点边集合
        /// 数组下标为顶点编号,对应内容是顶点的出度连接编号
        /// </summary>        
        private List<int[]> edge = new List<int[]>();

        /// <summary>
        /// 最长路径
        /// </summary>  
        private List<int> dist = new List<int>();

        /// <summary>
        /// 添加顶点
        /// </summary>
        /// <param name="nodeName">顶点字符串</param>
        /// <returns>
        ///     true: 顶点添加成功
        ///     false: 顶点编号重复
        /// </returns>
        public bool addNode(string nodeName)
        {
            if (noteIntDictionary.ContainsKey(nodeName) == false)
            {
                // 加入节点字典
                noteIntDictionary.Add(nodeName, cnt);
                noteStringDictionary.Add(cnt, nodeName);
                inDegree.Add(0); 
                dist.Add(0);
                edge.Add(emptyIntArray);
                cnt++;
                return true;
            }
            return false;
        }

        /// <summary>
        /// 为网络各顶点添加有向边,将终点转为数字编号
        /// </summary>
        /// <param name="nodeName">顶点字符串</param>
        /// <param name="nodeOutDegree">顶点出度数组</param>
        /// <returns></returns>
        public bool addEdge(string nodeName, string[] nodeOutDegree)
        {
            // 判断字典中是否含有该顶点
            if (noteIntDictionary.ContainsKey(nodeName) == true)
            {
                // 顶点字符串转为编号
                int nodeNum = noteIntDictionary[nodeName];
                int tempNum = edge[nodeNum].Length;
                int[] edgeNum = new int[tempNum + nodeOutDegree.Length];
                if (tempNum > 0)
                {
                    edge[nodeNum].CopyTo(edgeNum, 0);
                }
                for (int i = tempNum; i < nodeOutDegree.Length; i++)
                {
                    string nodeOutDegree_temp = nodeOutDegree[i];
                    // 判断字典中是否含有该节点
                    if (noteIntDictionary.ContainsKey(nodeOutDegree_temp) == false)
                    {
                        return false;
                    }
                    // 顶点添加出度编号
                    int nodeOutDegreeNum_temp = noteIntDictionary[nodeOutDegree_temp];
                    inDegree[nodeOutDegreeNum_temp]++;
                    edgeNum[i] = nodeOutDegreeNum_temp;
                }
                edge[nodeNum] = edgeNum;
                return true;
            }
            return false;
        }


        /// <summary>
        /// 拓扑排序
        /// </summary>
        /// <returns>
        /// true: 无环
        /// false: 有环
        /// </returns>
        public bool topologicalSort() 
        {
            Queue<int> zeroNode = new Queue<int>();
            List<int> inDegree_temp = new List<int>(inDegree);
            for (int i=0; i <cnt;++i)
            {
                if(inDegree_temp[i] == 0)
                {
                    zeroNode.Enqueue(i);
                }
            }
            int count = 0;
            while(zeroNode.Count != 0)
            {
                // TODO: 可能会出现异常
                int index = zeroNode.Dequeue();
                ++count;
                foreach(int nodeNum_temp in edge[index])
                {
                    --inDegree_temp[nodeNum_temp];
                    if(inDegree_temp[nodeNum_temp] == 0)
                    {
                        zeroNode.Enqueue(nodeNum_temp);
                    }
                }
            }
            return count == cnt;
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值