有趣生活

当前位置:首页>科技>欧拉算法可用于你了解欧拉的回路吗

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

发布时间:2026-07-20阅读(1)

导读文章目录​一:什么是欧拉回路?​​​​二:无向图中欧拉回路存在的条件​​​​三:如何得到欧拉的回路​​一:什么是欧拉回路?不知道你有没有玩过这样一种叫“一笔....文章目录
  • ​一:什么是欧拉回路?​​
  • ​​二: 无向图中欧拉回路存在的条件​​
  • ​​三:如何得到欧拉的回路​​
一:什么是欧拉回路?

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

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

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

欧拉回路问题:

如果图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"); } }}

测试:

输入:

Copyright © 2024 有趣生活 All Rights Reserve吉ICP备19000289号-5 TXT地图HTML地图XML地图