java搜索无向图中两点之间所有路径的算法

Java搜索无向图中两点之间所有路径的算法

算法思路

该算法使用深度优先搜索来查找两个节点之间的所有路径。在搜索期间,对于每个遍历到的未访问节点,我们可以标记它为已访问,并沿着它的所有未访问邻居递归搜索。在这个过程中,我们将到达一个目标节点作为目标终点,或遍历了所有的节点,这代表着没有路径可以到达目标终点,此时我们就回溯到上一步去探索其它可能的路径,直到找到所有的路径或者遍历完所有路径。

代码实现

代码实现分为如下几个步骤:

  1. 初始化所有节点为未访问状态,把起始节点添加到路径中,标记起始节点为已访问状态;
  2. 从起始节点开始深度优先搜索,对于每个遍历到的未访问节点,标记它为已访问,并将其添加到路径中;
  3. 如果当前节点为目标节点,则输出这个路径;
  4. 如果当前节点不是目标节点,则在继续递归搜索之前,搜索其所有未访问邻居节点;
  5. 回溯到上一个节点,回收资源,从路径中删除该节点并将其标记为未访问;
  6. 重复上述操作,直到搜索完所有路径。
public class Graph {
    private int V;
    private LinkedList<Integer>[] adj;

    public Graph(int v) {
        V = v;
        adj = new LinkedList[v];
        for (int i = 0; i < v; ++i) {
            adj[i] = new LinkedList();
        }
    }

    void addEdge(int v, int w) {
        adj[v].add(w); // Add w to v's list.
        adj[w].add(v); // Add v to w's list.
    }

    // A recursive function to print all paths from 'u' to 'd'.
    // visited[] keeps track of vertices in current path.
    // path[] stores actual vertices and path_index is current
    // index in path[]
    void printAllPathsUtil(int u, int d, boolean[] visited, int[] path, int pathIndex) {
        visited[u] = true;
        path[pathIndex] = u;
        pathIndex++;

        if (u == d) {
            for (int i = 0; i < pathIndex; i++) {
                System.out.print(path[i] + " ");
            }
            System.out.println("");
        } else {
            Iterator<Integer> i = adj[u].listIterator();
            while (i.hasNext()) {
                int n = i.next();
                if (!visited[n]) {
                    printAllPathsUtil(n, d, visited, path, pathIndex);
                }
            }
        }

        // Remove current vertex from path[] and mark it as unvisited
        pathIndex--;
        visited[u] = false;
    }

    void printAllPaths(int s, int d) {
        boolean[] visited = new boolean[V];
        int[] path = new int[V];
        int pathIndex = 0;
        // Initialize all vertices as not visited
        for (int i = 0; i < V; i++) {
            visited[i] = false;
        }

        // Call the recursive helper function to print all paths
        printAllPathsUtil(s, d, visited, path, pathIndex);
    }

    public static void main(String[] args) {
        Graph g = new Graph(4);
        g.addEdge(0, 1);
        g.addEdge(0, 2);
        g.addEdge(0, 3);
        g.addEdge(2, 0);
        g.addEdge(2, 1);
        g.addEdge(1, 3);

        int s = 2, d = 3;
        System.out.println("Following are all different paths from " + s + " to " + d);
        g.printAllPaths(s, d);
    }
}

示例说明

示例1

例如,我们有一个无向图,有四个节点,边的连接如下所示:

  0 ------- 1
  |         |
  |         |
  |         |
  2 ------- 3

我们要查找从节点2到节点3之间的所有路径,那么可以使用如下代码来实现:

Graph g = new Graph(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(0, 3);
g.addEdge(2, 0);
g.addEdge(2, 1);
g.addEdge(1, 3);

int s = 2, d = 3;
System.out.println("Following are all different paths from " + s + " to " + d);
g.printAllPaths(s, d);

输出结果为:

Following are all different paths from 2 to 3
2 0 1 3
2 1 3
2 0 3

可以看出,从节点2到节点3,有三条不同的路径,分别是2->0->1->3,2->1->3,2->0->3。

示例2

再例如,我们有一个无向图,有六个节点,边的连接如下所示:

     0 ----- 1
     |\     /|
     | \   / |
     |  \ /  |
     |   3   |
     |  / \  |
     | /   \ |
     |/     \|
     2 ----- 4
            |
            |
            |
            5

我们要查找从节点0到节点5之间的所有路径,那么可以使用如下代码来实现:

Graph g = new Graph(6);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(0, 3);
g.addEdge(1, 3);
g.addEdge(1, 4);
g.addEdge(2, 3);
g.addEdge(2, 4);
g.addEdge(3, 4);
g.addEdge(4, 5);

int s = 0, d = 5;
System.out.println("Following are all different paths from " + s + " to " + d);
g.printAllPaths(s, d);

输出结果为:

Following are all different paths from 0 to 5
0 1 3 4 5 
0 1 4 5 
0 2 3 4 5 
0 2 4 5 
0 3 4 5 

可以看出,从节点0到节点5,有五条不同的路径,分别是0->1->3->4->5,0->1->4->5,0->2->3->4->5,0->2->4->5,0->3->4->5。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java搜索无向图中两点之间所有路径的算法 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • SpringMVC的源码解析

    SpringMVC的源码解析攻略 SpringMVC是Spring框架中一个重要的模块,具有在Web开发中的优秀表现,如显式的分层体系结构、松散耦合、组件重用、可配置性和可扩展性。通过对SpringMVC的源码进行深入学习,可以更好地理解SpringMVC框架的设计原理、底层实现和优化方法。 以下是SpringMVC源码解析的完整攻略。 1. SpringM…

    Java 2023年5月16日
    00
  • Java日期时间字符串和毫秒相互转换的方法

    下面是详细讲解Java日期时间字符串和毫秒相互转换的方法的攻略。 一、Java日期时间字符串转毫秒 1.1 SimpleDateFormat类 在Java中,可以使用SimpleDateFormat类来完成日期时间字符串的转换。SimpleDateFormat是Java中日期时间格式化类的一个子类,它继承了DateFormat类,提供了非常方便的日期时间格式…

    Java 2023年5月20日
    00
  • Java多线程中的Balking模式详解

    让我来给您详细讲解一下“Java多线程中的Balking模式”的攻略。 什么是Balking模式 Balking是一种设计模式,它用于在并发编程中避免重复执行代码。这种模式通常用于程序中存在运行条件无法实现的情况下(例如正在发生的网络超时或其他必要资源无法访问等)。 Balking模式的实现过程 Balking模式的核心思想是,检查并避免尝试重复执行正在发生…

    Java 2023年5月18日
    00
  • jsp struts1 标签实例详解第2/2页

    下面我将详细讲解JSP Struts1标签实例详解的完整攻略。该攻略分为两页,这里我将着重对第二页进行讲解。 一、JSP Struts1标签实例详解(第2/2页) 本文主要对Struts标签库进行介绍,讲解它们的使用方法和常用属性。 1. html:submit(表单提交按钮) html:submit标签用于创建表单提交按钮。以下是html:submit标签…

    Java 2023年6月15日
    00
  • 如何用注解的方式实现Mybatis插入数据时返回自增的主键Id

    下面详细讲解如何用注解的方式实现Mybatis插入数据时返回自增的主键Id。 首先,在处理插入操作时,通常需要获取数据库自动生成的主键Id,以便后续处理。使用Mybatis时,可以使用useGeneratedKeys和keyProperty两个属性来实现此功能。 其中,useGeneratedKeys表示是否使用数据库自动生成的主键,默认值是false;而k…

    Java 2023年5月20日
    00
  • springboot自定义starter启动器的具体使用实践

    Spring Boot自定义Starter启动器的具体使用实践 在本文中,我们将详细讲解如何使用Spring Boot自定义Starter启动器,包括创建Starter、定义自动配置、使用自定义Starter等。 创建Starter 创建自定义Starter的第一步是创建一个Maven项目,并添加以下依赖: <dependency> <gr…

    Java 2023年5月15日
    00
  • Spring Boot 快速入门指南

    下面是关于 Spring Boot 快速入门指南的攻略: 概述 Spring Boot 是基于 Spring 框架的快速开发框架,通过自动装配和约定俗成的配置,可以快速搭建一个简单的 Java 应用。本文将介绍如何使用 Spring Boot 快速入门。 安装与配置 安装 Java 开发环境(JDK),最好使用 JDK 8 或以上版本。同时,也需要安装一个 …

    Java 2023年5月15日
    00
  • Springboot – Fat Jar示例详解

    Springboot – Fat Jar示例详解 什么是Fat Jar Fat Jar是指将程序所依赖的所有库和资源全部打包到一个Jar文件中。使用Fat Jar可以简化部署流程和环境配置过程,也可以避免因依赖库版本不一致造成的问题。 如何构建Fat Jar Spring Boot提供了插件来构建Fat Jar。我们可以在pom.xml文件中添加以下配置: …

    Java 2023年6月2日
    00
合作推广
合作推广
分享本页
返回顶部