我有一个代码可以在图中生成循环但是当点多的时候它就变慢了
本文关键字:候它 代码 有一个 循环 | 更新日期: 2023-09-27 18:18:15
我的代码如下,但它花了3分钟给出一个输出是否有一种更快的技术在无向图中找到循环:
当输入较少时,如下
{1, 2}, {1, 3}, {1, 4}, {2, 3},
{3, 4}, {2, 6}, {4, 6}, {7, 8},
{8, 9}, {9, 7}
它工作得很快,否则当它有太多的输入时,它就太慢了
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CycleDetection
{
class Program
{
// Graph modelled as list of edges
static int[,] graph =
{
{1, 2}, {1, 3}, {1, 4}, {2, 3},
{3, 4}, {2, 6}, {4, 6}, {7, 8},
{8, 9}, {9, 7}, {2, 3}, {1, 5}, {2, 4}, {4, 6},
{7, 4}, {3, 5}, {4, 5}, {2, 8},
{8, 1}, {9, 1}, {14,1}, {2,14}, {5, 1}, {7, 3}, {6, 2}, {10,1},
{10, 4}, {10, 6}, {10, 3}, {10,2},
{8, 3}, {1, 7}
};
static List<int[]> cycles = new List<int[]>();
static void Main(string[] args)
{
for (int i = 0; i < graph.GetLength(0); i++)
for (int j = 0; j < graph.GetLength(1); j++)
{
findNewCycles(new int[] { graph[i, j] });
}
foreach (int[] cy in cycles)
{
string s = "" + cy[0];
for (int i = 1; i < cy.Length; i++)
s += "," + cy[i];
Console.WriteLine(s);
}
Console.ReadLine();
}
static void findNewCycles(int[] path)
{
int n = path[0];
int x;
int[] sub = new int[path.Length + 1];
for (int i = 0; i < graph.GetLength(0); i++)
for (int y = 0; y <= 1; y++)
if (graph[i, y] == n)
// edge referes to our current node
{
x = graph[i, (y + 1) % 2];
if (!visited(x, path))
// neighbor node not on path yet
{
sub[0] = x;
Array.Copy(path, 0, sub, 1, path.Length);
// explore extended path
findNewCycles(sub);
}
else if ((path.Length > 2) && (x == path[path.Length - 1]))
// cycle found
{
int[] p = normalize(path);
int[] inv = invert(p);
if (isNew(p) && isNew(inv))
cycles.Add(p);
}
}
}
static bool equals(int[] a, int[] b)
{
bool ret = (a[0] == b[0]) && (a.Length == b.Length);
for (int i = 1; ret && (i < a.Length); i++)
if (a[i] != b[i])
{
ret = false;
}
return ret;
}
static int[] invert(int[] path)
{
int[] p = new int[path.Length];
for (int i = 0; i < path.Length; i++)
p[i] = path[path.Length - 1 - i];
return normalize(p);
}
// rotate cycle path such that it begins with the smallest node
static int[] normalize(int[] path)
{
int[] p = new int[path.Length];
int x = smallest(path);
int n;
Array.Copy(path, 0, p, 0, path.Length);
while (p[0] != x)
{
n = p[0];
Array.Copy(p, 1, p, 0, p.Length - 1);
p[p.Length - 1] = n;
}
return p;
}
static bool isNew(int[] path)
{
bool ret = true;
foreach (int[] p in cycles)
if (equals(p, path))
{
ret = false;
break;
}
return ret;
}
static int smallest(int[] path)
{
int min = path[0];
foreach (int p in path)
if (p < min)
min = p;
return min;
}
static bool visited(int n, int[] path)
{
bool ret = false;
foreach (int p in path)
if (p == n)
{
ret = true;
break;
}
return ret;
}
}
}
输出:-list of cycles
我使用visual studio 2010来运行这个
这样怎么样?
int[,] graph =
{
{1, 2}, {1, 3}, {1, 4}, {2, 3},
{3, 4}, {2, 6}, {4, 6}, {7, 8},
{8, 9}, {9, 7}, {2, 3}, {1, 5}, {2, 4}, {4, 6},
{7, 4}, {3, 5}, {4, 5}, {2, 8},
{8, 1}, {9, 1}, {14,1}, {2,14}, {5, 1}, {7, 3}, {6, 2}, {10,1},
{10, 4}, {10, 6}, {10, 3}, {10,2},
{8, 3}, {1, 7}
};
var g = graph.Cast<int>().ToArray();
var edges = Enumerable.Range(0, g.Length / 2)
.Select(i => Tuple.Create(g[i * 2], g[i * 2 + 1]));
var edgeLookup = edges.ToLookup(x => x.Item1);
var stack = new Stack<Tuple<int, int>>(edgeLookup.First());
var visited = new HashSet<Tuple<int, int>>();
while(stack.Count > 0)
{
var current = stack.Pop();
if(!visited.Add(current)) throw new Exception("cycle!!!");
var newNodes = edgeLookup[current.Item2];
foreach(var newNode in newNodes)
{
stack.Push(newNode);
}
}