寻找算法寻找欧拉路径

时间:2013-07-04 09:52:28

标签: algorithm graph-theory

我正在寻找一种算法来在图中找到Euler路径。

几周前我见过一个很好的,但我现在找不到它,我记得有标记边缘,偶数/奇数连接......

你知道一个类似,简单和直接的算法吗?

5 个答案:

答案 0 :(得分:16)

Graph-Magics.com开始,对于无向图,这将以相反的顺序给出游览,即从结束顶点到起始顶点:

  1. 从空堆栈和空电路(欧拉路径)开始。
    • 如果所有顶点均匀度:选择其中任何顶点。这将是当前的顶点。
    • 如果恰好有2个顶点具有奇数度:选择其中一个。这将是当前的顶点。
    • 否则不存在欧拉电路或路径。
  2. 重复步骤2,直到当前顶点不再有邻居并且堆栈为空。

    1. 如果当前顶点没有邻居:
      • 将其添加到电路中,
      • 从堆栈中删除最后一个顶点并将其设置为当前顶点。
    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();            
    }