我正在寻找一种算法来在图中找到Euler路径。
几周前我见过一个很好的,但我现在找不到它,我记得有标记边缘,偶数/奇数连接......
你知道一个类似,简单和直接的算法吗?
答案 0 :(得分:16)
从Graph-Magics.com开始,对于无向图,这将以相反的顺序给出游览,即从结束顶点到起始顶点:
重复步骤2,直到当前顶点不再有邻居并且堆栈为空。
否则:
答案 1 :(得分:3)
Hierholzer算法是在有向图中找到Euler路径的更好方法。
http://stones333.blogspot.com/2013/11/find-eulerian-path-in-directed-graph.html
它有代码和测试用例。
答案 2 :(得分:3)
我没有任何语言的代码,但我知道算法,如何查找,我会在这里写。
假设我们有n个节点的图形。我们将连接到该节点的边的节点数称为度。首先,我们应该说每个节点的和度甚至可以根据“握手问题”。
现在假设我们有一些Euler路径p从节点s开始到结束节点f。然后对于不同于st和t的每个节点,每次我们进入该节点时,我们应该离开(如果我们不离开,那么我们将不会到达最终的f节点),所以对于这些节点,度数将是均匀的,对于s和f,如果它们是不同的程度将是奇数,因为我们在第一次离开s,然后在每次进入之后,我们离开s节点,所以将有1 + 2 * n度,其中n是数字有时我们再次访问过。同样适用于f。如果存在欧拉路径,那么应该有2个奇数度的节点。如果有欧拉圆,那么每个节点的度数应该是偶数,如果是这种情况,那么我们选择哪个节点作为s无关紧要,我们也将在s中结束圆。
现在的问题是如何获得欧拉圆/路径。这里我们需要在图中定义“桥”。 Bridge是具有特定属性的边缘,如果我们删除该边缘,那么在剩余图形中,组件数量将增加1。换句话说,桥是一个边,它是图中某些两个组件的唯一连接边。
由于我们知道桥是什么,我们可以定义算法。如果恰好存在2个具有均匀度的节点: 1)我们从其中一个开始,通过选择连接到当前节点的边缘前进到下一个节点。 2)如果我们应该选择桥梁和非桥梁之间的边缘,我们应该总是选择无桥梁。 3)如果剩下节点非桥边缘,那么我们就可以选择任何桥梁。
如果没有奇数度的节点,那么我们可以从任何节点开始并遵循这3条规则。
这是始终有效的整个算法。 这里有一些有用的链接。
https://www.math.ku.edu/~jmartin/courses/math105-F11/Lectures/chapter5-part2.pdf http://www.graph-magics.com/articles/euler.php
答案 3 :(得分:0)
如果图形恰好有两个具有奇数度的顶点,则存在一个欧拉路径。这些顶点实际上是欧拉路径的终点。
所以你可以找到一个具有奇数度的顶点并开始用DFS遍历图形:当你移动时有一个被访问的数组用于边缘。不要遍历边缘两次。
如果顶点没有剩余边缘,请检查是否已访问过所有边缘,如果已完成。
要存储实际的euler路径,您可以保留一个前导数组,该数组将前一个顶点存储在路径中。
答案 4 :(得分:0)
所以这是我的解决方案,我已经使用finally块打印出来,因为我得到异常“堆栈是空的”,我没有时间来解决这个问题。我希望这有助于某人!
public void EulerTour()
{
GetInput(); //gets the adjency matrix
int start = NodeList[0]; //start from any vertex, i choose 0
tempPath.Push(NodeList[0]); //temporary path - stack
try
{
while (tempPath.Count != 0)
{
for (int i = 0; i < total; i++)
{
if (adjencyMatrix[start, i] == 'd')
{
tempPath.Push(NodeList[i]);
adjencyMatrix[start, i] = 'n';
adjencyMatrix[i, start] = 'n';
if (!hasNeighbour((int)tempPath.Peek())) //checks if current node has any neighbour
{
while (!hasNeigbour((int)tempPath.Peek()))
{
finalPath.Push(tempPath.Pop());
}
start = (int)tempPath.Peek();
}
else
{
start = i;
break;
}
}
}
}
}
catch
{
Console.WriteLine("Print: ");
}
finally
{
foreach (object o in finalPath)
{
Console.Write(o.ToString() + "---->");
}
}
Console.ReadKey();
}