代碼實現
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;
}
}
}