欧拉算法可用于(你了解欧拉的回路吗)

文章目录
  • ​一:什么是欧拉回路?​​
  • ​​二: 无向图中欧拉回路存在的条件​​
  • ​​三:如何得到欧拉的回路​​
一:什么是欧拉回路?

不知道你有没有玩过这样一种叫“一笔画”,从某一点开始画一个图形或图案,期间笔不能从纸上离开而且每条边只能画一次。

下面有三个例子,你可以先试一试看看能不能“一笔画”

欧拉算法可用于(你了解欧拉的回路吗)(1)

欧拉算法可用于(你了解欧拉的回路吗)(2)

欧拉算法可用于(你了解欧拉的回路吗)(3)

第一个图其实是根本画不出来的,第二个图可以画出来,但是不存在起点和终点为同一点的情况,第三个图可以轻松画出来,而且存在起点和终点为同一点的情况

欧拉回路问题:

如果图G中的一个路径包括每个边恰好一次,则该路径称为欧拉路径(Euler path)。

如果一个回路是欧拉路径,则称为欧拉回路(Euler circuit)。

具有欧拉回路的图称为欧拉图(简称E图)。具有欧拉路径但不具有欧拉回路的图称为半欧拉图。

二: 无向图中欧拉回路存在的条件

什么情况下才存在欧拉回路呢?

充要条件:当且仅当图是连通的而且每个顶点的度是偶数

想象一下,如果一个节点​​ ​v​ ​​的度为1,那么进入​ ​v​ ​​后只能留在​ ​v​ ​中,不可能再出来。

但是当有两个多为奇数的节点分别作为起点和终点, 欧拉路径 还是有可能存在的,如果奇数度的顶点多余两个,连欧拉路径都不可能存在。

三:如何得到欧拉回路

求解起点和终点重合的欧拉回路问题可以基于深度优先思想来实现,与DFS算法的区别就是,DFS算法中每个节点基本上只会访问一遍,而欧拉回路算法中要求放宽,只是每个边只能访问一边,但是某一个节点可以多次访问,但基本思想是一致的。DFS算法

深度优先搜索的主要问题在于当访问返回开始节点时,可能还剩下某些边没有访问到,也就是访问提前结束了,比较好的补救方法就是,在那些没有访问到的路径的第一个节点重新开始新一轮深度优先搜索,将新的回路加到原来回路中,继续此过程直到所有的边都被遍历为止

四:Java实现

import java.util.*; /** * @author ht113 */ public class EulerCircuit { private List<Integer> path; /** * this cost O(|E| |V|) time * @param unDirectedEdges: adjacency matrix,[1,2] represents edge from node1 to node2 * @param n: the num of nodes * @param k: the start node of Euler Circuit * @return * @throws NotFoundException */ public List<Integer> EulerCircuitByDFS(int[][] unDirectedEdges, int n, int k) throws NotFoundException{ if (unDirectedEdges==null||unDirectedEdges.length<=1||n<=2) { throw new NotFoundException(); } //init undirected graph,use adjacency list //{key:1, value:<2, 3>} represents edge from node1 to node2,node3 Map<Integer, List<Integer>> graph = new HashMap<>(); //making graph takes O(E) //iterate the adjacency matrix for(int i = 0; i<unDirectedEdges.length; i ) { int[] edge = unDirectedEdges[i]; //add (edge[0], edge[1]) if (!graph.containsKey(edge[0])) { graph.put(edge[0], new ArrayList<Integer>()); } graph.get(edge[0]).add(edge[1]); //add (edge[1], edge[0]) if (!graph.containsKey(edge[1])) { graph.put(edge[1], new ArrayList<Integer>()); } graph.get(edge[1]).add(edge[0]); } path = new ArrayList<>(); //ECDFS takes O(V) try { ECDFS(graph, k, k, path); }catch (NotFoundException e){ throw e; } return path; } /** * special dfs for Euler Circuit * @param graph * @param k: start node * @param origin: the origin start node * @param currentPath * @throws NotFoundException */ public void ECDFS(Map<Integer, List<Integer>> graph, int k, int origin, List<Integer> currentPath) throws NotFoundException{ currentPath.add(k); for(int i = 0; i<graph.get(k).size(); i ){ int neighbor = graph.get(k).get(i); //and the degree of node w is odd if(neighbor!=origin && graph.get(neighbor).size()%2!=0){ throw new NotFoundException(); } graph.get(k).remove(i); graph.get(neighbor).remove(Integer.valueOf(k)); //when dfs return to the origin start node //some edges may not have been visited if(neighbor==origin){ currentPath.add(origin); boolean allSeen; do{ boolean tmp = true; for(int j = 0; j<currentPath.size(); j ) { int entryNode = currentPath.get(j); tmp &= graph.get(entryNode).size() == 0; if(!tmp) { List<Integer> tempPath = new ArrayList<>(); ECDFS(graph, entryNode, entryNode , tempPath); //add child circuit path int index = currentPath.indexOf(entryNode); currentPath.remove(index); currentPath.addAll(index, tempPath); } } allSeen = tmp; }while (!allSeen); return; } else { ECDFS(graph, neighbor, origin, currentPath); } } } public static class NotFoundException extends Exception{ public NotFoundException(){ super("Euler Circuit Not Found"); } } }

测试:

欧拉算法可用于(你了解欧拉的回路吗)(4)

欧拉算法可用于(你了解欧拉的回路吗)(5)

输入:

unDirectedEdges

n

k

{{1,3}, {1,4}, {2,3}, {2,8}, {3,4}, {3,6}, {3,7},{3,9}, {4,5}, {4,7}, {4,10}, {4,11}, {5,10}, {6,9}, {7,9},{7,10}, {8,9}, {9,10}, {9,12}, {10,11}, {10,12}}

12

5

{{1,3},{1,2},{3,4}, {2,3}, {2,4}};

4

4

预计输出:

​​ ​某一条从节点5开始节点5结束的欧拉回路​ ​

​ ​Euler Circuit Not Found​ ​

实际输出:

​​ ​[5, 4, 1, 3, 2, 8, 9, 10, 12, 9, 3, 4, 7, 3, 6, 9, 7, 10, 4, 11, 10, 5]​ ​

​ ​Euler Circuit Not Found​ ​

测试通过

你可能还敢兴趣的图论算法(均附Java实现代码):

  • 算法实验–主函数只有五行的Floyed的算法以及最短路径输出
  • 你必须会的–Dijkstra算法–单源最短路径问题
  • 你必须会的DFS的递归实现与堆栈实现
  • 你必须会的启发式搜索算法–A*算法
,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页