JAVA代码详解:无向图中判断欧拉路径和欧拉回路

JAVA代码详解:无向图中判断欧拉路径和欧拉回路

欧拉回路(Euler Circuit)是数学家欧拉(Euler)在研究著名的德国哥尼斯堡(Koenigsberg)七桥问题时发现的。

如下图所示,流经哥尼斯堡的普雷格尔河中有两个岛,两个岛与两岸共4处陆地通过7座桥彼此相联。7桥问题就是如何能从任一处陆地出发,经过且经过每个桥一次后回到原出发点。

欧拉由此提出了著名的欧拉定理。

1)欧拉路(Euler Path):通过图中所有边的简单路。

2)欧拉回路(Euler Circuit):闭合的欧拉路。

3)欧拉图(Euler Graph):包含欧拉回路的图。

JAVA代码详解:无向图中判断欧拉路径和欧拉回路_第1张图片

欧拉原理及定义

欧拉路:图G,若存在一条路,经过G中每条边有且仅有一次,称这条路为欧拉路。

欧拉回路:图G,如果存在一条回路经过G每条边有且仅有一次,称这条回路为欧拉回路。

欧拉图:具有欧拉回路的图成为欧拉图。

判断欧拉路是否存在的方法

有向图:图连通,有一个顶点出度大入度1,有一个顶点入度大出度1,其余都是 出度=入度。

无向图:图连通,只有2个顶点是奇数度,其余都是偶数度的。

判断欧拉回路是否存在的方法

有向图:图连通,所有的顶点出度=入度。

无向图:图连通,所有顶点都是偶数度。

推论:

1、凡是由偶点组成的连通图,一定可以一笔画成。

2、凡是只有两个奇点的连通图(其余都为偶点),一定可以一笔画成。

3、其他情况的图都不能一笔画出。 


如图1所示:图1是一个无向图,图中有5个顶点(Vertex),5条边(Edge)。

这个图中存在欧拉路(Euler Path),例如:4-3-0-1-2-0;但是不存在欧拉回路(Euler Circuit)。

注意:顶点0具有奇数度(3);顶点4具有奇数度(1)

 

JAVA代码详解:无向图中判断欧拉路径和欧拉回路_第2张图片

如图2所示:图2的无向图存在欧拉回路(Euler Circuit),例如:2-1-0-3-4-0-2。

所有顶点的度都是偶数度。

JAVA代码详解:无向图中判断欧拉路径和欧拉回路_第3张图片

如图3所示:图3的无向图不是一张欧拉图(Euler Graph),因为不包含欧拉回路(Euler Circuit)。

图3中有4个顶点都是奇数度。

JAVA代码详解:无向图中判断欧拉路径和欧拉回路_第4张图片

通过编写一个JAVA算法来判断一张无向图是否存在欧拉路径,欧拉回路。 


算法设计

package com.bean.algorithm.basic;

import java.util.Iterator;
import java.util.LinkedList;


public class EulerCircuit2 {

	private int V;   // 顶点( vertices)的数量 
	  
    // 邻接表( Adjacency List Representation)表示 
    private LinkedList adj[]; 
  
    // 构造方法 
    EulerCircuit2(int v) 
    { 
        V = v; 
        adj = new LinkedList[v]; 
        for (int i=0; i i = adj[v].listIterator(); 
        while (i.hasNext()) 
        { 
            int n = i.next(); 
            if (!visited[n]) 
                DFSUtil(n, visited); 
        } 
    } 
  
    // 检查所有非零度顶点是否连接 
    boolean isConnected() 
    { 
        // 标记所有顶点为未访问状态 
        boolean visited[] = new boolean[V]; 
        int i; 
        for (i = 0; i < V; i++) 
            visited[i] = false; 
  
        // 找到非0度的顶点 
        for (i = 0; i < V; i++) 
            if (adj[i].size() != 0) 
                break; 
   
        if (i == V) 
            return true; 
  
        DFSUtil(i, visited); 
  
        for (i = 0; i < V; i++) 
           if (visited[i] == false && adj[i].size() > 0) 
                return false; 
  
        return true; 
    } 
  
    /* 返回值说明 
       0 --> 图不是欧拉图 Eulerian则返回0 
       1 --> 如果图中存在欧拉路则返回1 (Semi-Eulerian) 
       2 --> 如果图中存在欧拉回路则返回2 Euler Circuit (Eulerian)  */
    int isEulerian() 
    { 
        // 检查是否连接了所有非零度顶点 
        if (isConnected() == false) 
            return 0; 
  
        // 统计奇数度的顶点 
        int odd = 0; 
        for (int i = 0; i < V; i++) 
            if (adj[i].size()%2!=0) 
                odd++; 
  
        // If count is more than 2, then graph is not Eulerian 
        if (odd > 2) 
            return 0; 
  
        // If odd count is 2, then semi-eulerian. 
        // If odd count is 0, then eulerian 
        // Note that odd count can never be 1 for undirected graph 
        return (odd==2)? 1 : 2; 
    } 
  
    // Function to run test cases 
    public void test() 
    { 
        int res = isEulerian(); 
        if (res == 0) 
            System.out.println("图 不是 欧拉图 Eulerian"); 
        else if (res == 1) 
            System.out.println("图 包含 欧拉路 Euler path"); 
        else
           System.out.println("图 包含 欧拉回路 Euler cycle"); 
    } 


	public static void main(String args[]) {
		
		EulerCircuit2 g1 = new EulerCircuit2(5); 
        g1.addEdge(1, 0); 
        g1.addEdge(0, 2); 
        g1.addEdge(2, 1); 
        g1.addEdge(0, 3); 
        g1.addEdge(3, 4); 
        g1.test(); 
  
        EulerCircuit2 g2 = new EulerCircuit2(5); 
        g2.addEdge(1, 0); 
        g2.addEdge(0, 2); 
        g2.addEdge(2, 1); 
        g2.addEdge(0, 3); 
        g2.addEdge(3, 4); 
        g2.addEdge(4, 0); 
        g2.test(); 
  
        EulerCircuit2 g3 = new EulerCircuit2(5); 
        g3.addEdge(1, 0); 
        g3.addEdge(0, 2); 
        g3.addEdge(2, 1); 
        g3.addEdge(0, 3); 
        g3.addEdge(3, 4); 
        g3.addEdge(1, 3); 
        g3.test(); 
		
		EulerCircuit2 g4 = new EulerCircuit2(6); // 6个顶点,10条边
		g4.addEdge(0, 1);
		g4.addEdge(1, 2);
		g4.addEdge(2, 0);
		g4.addEdge(3, 4);
		g4.addEdge(4, 5);
		g4.addEdge(5, 3);
		g4.addEdge(0, 3);
		g4.addEdge(0, 5);
		g4.addEdge(2, 3);
		g4.addEdge(2, 5);
		g4.test();
	
		EulerCircuit2 g5 = new EulerCircuit2(5);
		g5.addEdge(0, 1);
		g5.addEdge(0, 2);
		g5.addEdge(1, 2);
		g5.addEdge(1, 3);
		g5.addEdge(1, 4);
		g5.addEdge(4, 2);
		g5.addEdge(4, 3);
		g5.addEdge(2, 3);
		g5.test();

		
		EulerCircuit2 g6 = new EulerCircuit2(3);
		g6.addEdge(0, 1);
		g6.addEdge(1, 2);
		g6.addEdge(2, 0);
		g6.test();

		EulerCircuit2 g7 = new EulerCircuit2(3);
		g7.test();
	}
}

程序运行结果:

图 包含 欧拉路 Euler path
图 包含 欧拉回路 Euler cycle
图 不是 欧拉图 Eulerian
图 包含 欧拉回路 Euler cycle
图 包含 欧拉路 Euler path
图 包含 欧拉回路 Euler cycle
图 包含 欧拉回路 Euler cycle

 

你可能感兴趣的:(算法分析与设计)