图的遍历(Java语言)

图有两种遍历方式:深度优先遍历(DFS)和广度优先遍历(BFS)。

深度优先遍历

首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直到图中所有和v有路径相通的顶点均已被访问为止。若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的出发点重复上述过程,直至图中所有顶点均已被访问为止。
在这里插入图片描述
DFS:

//邻接矩阵的深度优先搜索
public void dfs(int v) {
        System.out.print(getVertex(v) + " ");  //先输出此顶点
        marked[v] = true; //把遍历过的顶点标记为true
        for (int w = adj(v); w < vertexList.size(); w++) { //w下标对应的顶点是v下标对应顶点的邻接点
            if(edges[v][w] != 0 && !marked[w]) { //如果该顶点和它的邻接点之间可以连接并且该顶点的邻接点没有被遍历
                dfs(w); //对该顶点的邻接点进行深度优先搜索
            }
        }
    }

广度优先遍历

首先访问出发点v,接着依次访问v的所有邻接点w1,w2,…,wt。然后再依次访问与w1,w2,…,wt邻接的所有未曾访问过的顶点。依此类推,直至图中所有和起点v有路径相通的顶点都已访问到为止。此时从v开始的搜索过程结束。
若G是连通图,则一次就能搜索完所有节点;否则在图G中另选一个尚未访问的顶点作为新出发点继续上述的遍历过程,直至G中所有顶点均已被访问为止。
在这里插入图片描述
BFS:

//邻接矩阵的广度优先搜索
    public void bfs(int i) {
        LinkedList<Integer> list = new LinkedList<Integer>(); //创建一个链表
        marked[i] = true; //从给定的顶点出发,先把该顶点标记为访问过
        list.addLast(i); //把该顶点对应的下标加入list中

        while (!list.isEmpty()) { //该链表不为空
            int v = list.removeFirst(); //定义一个变量v来存储从链表中取出的第一个下标元素
            System.out.print(getVertex(v) + " ");  //输出该元素对应的顶点
            for (int w = adj(v); w < vertexList.size(); w++) { //遍历以下标v为顶点的每一个邻接点的下标
                if(edges[v][w] != 0 && !marked[w]) { //如果该顶点和它的邻接点之间可以连接并且该顶点的邻接点没有被遍历
                    marked[w] = true; //把该顶点的邻接点标记为访问过
                    list.addLast(w); //把该顶点的邻接点加入链表的链尾
                }
            }
        }
    }

创建一个图并使用两种遍历方式遍历:

Graph类:

package com.graph;
import java.util.*;
public class Graph {
    ArrayList<String> vertexList; //存储顶点的集合
    int[][] edges; //存储图对应的邻接矩阵
    int numEdges; //表示边的条数
    boolean[] marked; //标记是否被遍历过
    public Graph(int n) {
        //初始化存储顶点的集合、初始化矩阵
        vertexList = new ArrayList<String>(n);
        edges = new int[n][n];
        marked = new boolean[n];
    }
    //找当前节点的邻接结点对应的下标w
    public int adj(int v) {
        for (int w = 0; w < vertexList.size(); w++) {
            if(edges[v][w] != 0) {
                return w;
            }
        }
        return -1;
    }
    /**
     * 深度优先搜索
     * @param v 传入要开始遍历的顶点的下标(从下标为v的顶点开始遍历)
     */
    public void dfs(int v) {
        System.out.print(getVertex(v) + " ");  //先输出此顶点
        marked[v] = true; //把遍历过的顶点标记为true
        for (int w = adj(v); w < vertexList.size(); w++) { //w下标对应的顶点是v下标对应顶点的邻接点
            if(edges[v][w] != 0 && !marked[w]) { //如果该顶点和它的邻接点之间可以连接并且该顶点的邻接点没有被遍历
                dfs(w); //对该顶点的邻接点进行深度优先搜索
            }
        }
    }
    //广度优先搜索
    public void bfs(int i) {
        LinkedList<Integer> list = new LinkedList<Integer>(); //创建一个链表
        marked[i] = true; //从给定的顶点出发,先把该顶点标记为访问过
        list.addLast(i); //把该顶点对应的下标加入list中

        while (!list.isEmpty()) { //该链表不为空
            int v = list.removeFirst(); //定义一个变量v来存储从链表中取出的第一个下标元素
            System.out.print(getVertex(v) + " ");  //输出该元素对应的顶点
            for (int w = adj(v); w < vertexList.size(); w++) { //遍历以下标v为顶点的每一个邻接点的下标
                if(edges[v][w] != 0 && !marked[w]) { //如果该顶点和它的邻接点之间可以连接并且该顶点的邻接点没有被遍历
                    marked[w] = true; //把该顶点的邻接点标记为访问过
                    list.addLast(w); //把该顶点的邻接点加入链表的链尾
                }
            }
        }
    }
    //对dfs进行方法重载,遍历所有顶点(防止漏掉没有任何指向的顶点)
    public void dfs() {
        for (int i = 0; i < vertexList.size(); i++) {
            if(!marked[i]) {
                dfs(i);
            }
        }
    }
    对bfs进行方法重载,遍历所有顶点(防止漏掉没有任何指向的顶点)
    public void bfs() {
        marked = new boolean[vertexList.size()]; //再调用了dfs之后若调用bfs,须重新new个marked数组,否则经过dfs之后marked数组的值都为true
        for (int i = 0; i < vertexList.size(); i++) {
            if(!marked[i]) {
                bfs(i);
            }
        }
    }
    //返回给定下标的顶点值
    public String getVertex(int index) {
        return vertexList.get(index);
    }
    //返回顶点的个数
    public int numVertex() {
        return vertexList.size();
    }
    //返回边的条数
    public int numEdges() {
        return numEdges;
    }
    //显示图对应的矩阵
    public void showGraph() {
        for(int[] link : edges) {
            System.out.println(Arrays.toString(link));
        }
    }
    //返回v1和v2的权值
    public int weight(int v1, int v2) {
        return edges[v1][v2];
    }
    //插入结点
    public void insertVertex(String vertex) {
        vertexList.add(vertex);
    }
    //添加边

    /**
     *
     * @param v1 表示第一个顶点对应的下标
     * @param v2 表示第二个顶点对应的下标
     * @param w 表示它们两个顶点之间的关系。(w值为1表示两个顶点能够直接连接,为0表示不能直接连接)
     */
    public void insertEdge(int v1, int v2, int w) {
        edges[v1][v2] = w;
        edges[v2][v1] = w;
        numEdges++;
    }
}

测试类:

package com.graph;

public class GraphDemo {
    public static void main(String[] args) {
        String[] vertexes = {"A","B","C","D","E","F","G","H","I"};
        Graph graph = new Graph(vertexes.length);
        //添加顶点
        for(String vertex : vertexes) {
            graph.insertVertex(vertex);
        }
        //添加边
        graph.insertEdge(0,1,1);
        graph.insertEdge(0,5,1);
        graph.insertEdge(1,2,1);
        graph.insertEdge(1,6,1);
        graph.insertEdge(1,8,1);
        graph.insertEdge(2,3,1);
        graph.insertEdge(2,8,1);
        graph.insertEdge(3,8,1);
        graph.insertEdge(3,4,1);
        graph.insertEdge(3,6,1);
        graph.insertEdge(3,7,1);
        graph.insertEdge(4,5,1);
        graph.insertEdge(4,7,1);
        graph.insertEdge(5,6,1);
        graph.insertEdge(6,7,1);
        graph.showGraph();
        System.out.println("DFS:");
        graph.dfs();
        System.out.println();
        System.out.println("BFS:");
        graph.bfs();
    }
}

结果:
在这里插入图片描述

  • 21
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
### 回答1: 在Java中,我们可以使用while循环或者for循环来遍历LinkedList。以下是使用while循环遍历LinkedList的示例代码: ```java import java.util.LinkedList; public class LinkedListTraversalExample { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); // 使用while循环遍历LinkedList LinkedList<String>.Node currentNode = linkedList.getFirst(); while(currentNode != null) { System.out.println(currentNode.item); currentNode = currentNode.next; } } } ``` 在上面的示例中,我们首先创建一个LinkedList对象并向其中添加了三个元素。然后,我们使用`getFirst()`方法获取LinkedList的第一个节点,并将其赋值给currentNode变量。接下来,我们使用while循环遍历LinkedList,直到currentNode为null。在循环内部,我们打印currentNode的item值,并将currentNode更新为下一个节点,以便下一次循环。 使用for循环遍历LinkedList的示例代码如下: ```java import java.util.LinkedList; public class LinkedListTraversalExample { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); // 使用for循环遍历LinkedList for(String element : linkedList) { System.out.println(element); } } } ``` 在上面的示例中,我们使用for-each循环遍历LinkedList。在循环内部,我们打印当前元素的值。由于LinkedList实现了Iterable接口,因此我们可以使用for-each循环来遍历其元素。 ### 回答2: LinkedList 是 Java 中的一种双向链表数据结构,它的特点是可以在任意位置进行元素的插入和删除操作。要遍历 LinkedList,我们可以使用迭代器或者循环来实现。 使用迭代器遍历 LinkedList 是常用的方法之一。我们可以通过调用 LinkedList 对象的 `iterator` 方法来获取一个迭代器。然后,使用 `hasNext` 方法判断是否还有下一个元素,使用 `next` 方法获取下一个元素。我们可以在一个循环中不断调用这两个方法来遍历 LinkedList,直到没有下一个元素为止。 另一种遍历 LinkedList 的方法是使用循环。通过获取 LinkedList 的大小,我们可以使用一个 for 循环来遍历 LinkedList。通过调用 LinkedList 对象的 `get` 方法,我们可以按索引获取每一个元素。 下面是使用迭代器和循环两种方法遍历一个 LinkedList 的示例代码: ``` import java.util.LinkedList; import java.util.Iterator; public class LinkedListTraversal { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<String>(); linkedList.add("A"); linkedList.add("B"); linkedList.add("C"); // 使用迭代器遍历 LinkedList Iterator<String> iterator = linkedList.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); } // 使用循环遍历 LinkedList for (int i = 0; i < linkedList.size(); i++) { String element = linkedList.get(i); System.out.println(element); } } } ``` 以上就是使用迭代器和循环两种方法遍历 LinkedList 的实现方式。无论是使用迭代器还是循环,遍历 LinkedList 都是比较简单的操作。 ### 回答3: LinkedList是Java语言中提供的一种双向链表数据结构,它可以存储各种类型的数据,并且可以动态地增删元素。在LinkedList中,每个元素都包含一个指向前一个节点和后一个节点的指针。 要遍历LinkedList,我们可以使用两种常见的方法:使用Iterator迭代器和使用普通的for循环。 首先,使用Iterator迭代器遍历LinkedList可以通过以下步骤实现: 1. 创建LinkedList对象,并添加一些元素。 2. 获取LinkedList的Iterator对象,使用LinkedList的`iterator()`方法。 3. 使用Iterator的`hasNext()`方法判断是否还有下一个元素,如果有,继续执行步骤4;如果没有,跳到步骤6。 4. 使用Iterator的`next()`方法获取当前元素,并对该元素进行操作。 5. 回到步骤3继续判断下一个元素。 6. 遍历结束。 下面是一个使用Iterator迭代器遍历LinkedList的示例代码: ``` import java.util.Iterator; import java.util.LinkedList; public class LinkedListTraversal { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("A"); linkedList.add("B"); linkedList.add("C"); Iterator<String> iterator = linkedList.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); } } } ``` 另外,我们还可以使用普通的for循环来遍历LinkedList,具体步骤如下: 1. 创建LinkedList对象,并添加一些元素。 2. 使用LinkedList的`size()`方法获取LinkedList的大小。 3. 使用普通的for循环从0到LinkedList的大小减一(即`size()-1`)遍历LinkedList。 4. 使用LinkedList的`get()`方法获取当前索引对应的元素,并对该元素进行操作。 下面是一个使用普通的for循环遍历LinkedList的示例代码: ``` import java.util.LinkedList; public class LinkedListTraversal { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("A"); linkedList.add("B"); linkedList.add("C"); for (int i = 0; i < linkedList.size(); i++) { String element = linkedList.get(i); System.out.println(element); } } } ``` 综上所述,我们可以使用Iterator迭代器或普通的for循环来遍历LinkedList,根据具体情况选择不同的遍历方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值