(九)图——图的遍历

1、基本介绍

 深度优先遍历

 步骤:

广度优先遍历

 步骤:

2、应用实例

package graph;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

public class GraphTraverse {
    public static void main(String[] args) {
        String[] vertexs = {"A","B","C","D","E"};
        Graph graph = new Graph(vertexs.length);

        //  插入节点
        for (String vertex : vertexs) {
            graph.insertVertex(vertex);
        }

        //  插入边
        graph.insertEdge(0, 1, 1);
        graph.insertEdge(0, 2, 1);
        graph.insertEdge(1, 0, 1);
        graph.insertEdge(1, 2, 1);
        graph.insertEdge(1, 3, 1);
        graph.insertEdge(1, 4, 1);
        graph.insertEdge(2, 0, 1);
        graph.insertEdge(2, 1, 1);
        graph.insertEdge(3, 1, 1);
        graph.insertEdge(4, 1, 1);

        System.out.println("图的顶点个数:" + graph.getNumOfVertex());
        System.out.println("图的边的条数:" + graph.getNumOfEdges());
        graph.showGraph();   //  打印矩阵(图)

        //  深度优先搜索
        System.out.print("深度优先搜索:");
        graph.dfs(0);

        //  广度优先搜索
        System.out.print("\n广度优先搜索:");
        graph.bfs(1);
    }
}

class Graph {
    public List<String> vertexLists; // 存储顶点的集合
    public int[][] edges;            // 存储边的二维数组
    public int numOfVertex;          // 顶点的个数
    public int numOfEdges;           // 边的条数
    public boolean[] isVisited;      // 记录该节点是否被访问过
    public Graph (int numOfVertex) {
        vertexLists = new ArrayList<>(numOfVertex);
        edges = new int[numOfVertex][numOfVertex];
        this.numOfVertex = numOfVertex;
        this.numOfEdges = 0;
        isVisited = new boolean[numOfVertex];
    }

    //  插入顶点
    public void insertVertex(String vertex) {
        vertexLists.add(vertex);
    }

    //  插入边
    /*
        v1:第一个顶点的下标
        v2:第二个顶点的下标
        w:权值,默认为1,表示这两个顶点有边
     */
    public void insertEdge(int v1, int v2, int w) {
        edges[v1][v2] = w;
        edges[v2][v1] = w;
        this.numOfEdges++;
    }

    //  打印图
    public void showGraph() {
        for (int[] temp : edges) {
            System.out.println(Arrays.toString(temp));
        }
        System.out.println();
    }

    //  返回该图的顶点个数
    public int getNumOfVertex() {
        return this.numOfVertex;
    }

    //  返回该图的边的条数
    public int getNumOfEdges() {
        return (this.numOfEdges >> 1);
    }

    //  查找当前节点的下一个邻接点
    //  @返回对应节点的下标
    public int getFirstNeighbor(int index) {
        for (int i = 0; i < vertexLists.size(); i++) {
            if (edges[index][i] > 0) { // 大于0,表示有边
                return i;
            }
        }
        return -1;
    }

    //  查找当前节点的邻接点的下一个邻接点
    //  @返回对应节点的下标
    public int getNextNeighbor(int index, int v1) {
        for (int i = v1 + 1; i < vertexLists.size(); i++) {
            if (edges[index][i] > 0) {
                return i;
            }
        }
        return -1;
    }

    //  深度优先搜索
    public void dfs(int v) {
        //  输出当前节点
        System.out.print(vertexLists.get(v) + " ");

        //  标记当前节点为已访问节点
        isVisited[v] = true;

        //  查找当前节点的第一个邻接点
        int w = getFirstNeighbor(v);

        //  判断邻接点是否存在
        while (w != -1) {
            //  判断该邻接点是否已访问过
           if (!isVisited[w]) {
                dfs(w);
            }
            //  如果该邻接点已访问过,则找该邻接点的下一个邻接点
            w = getNextNeighbor(v, w);
        }

    }

    //  广度优先搜索
    public void bfs(int v) {
        //  用于存放节点
        List queue = new LinkedList();
        boolean[] isVisited = new boolean[this.numOfVertex]; // 不能用原有的isVisited数组,因为dfs时已被修改

        //  输出当前节点
        System.out.print(vertexLists.get(v) + " ");

        //  标记当前节点为访问节点
        isVisited[v] = true;

        //  将当前节点入队
        queue.add(v);

        while(queue.size() > 0) {
            //  取出队首节点
            int u = (Integer) queue.remove(0);

            //  获取该节点的第一个邻接点
            int w = getFirstNeighbor(u);

            // 判断该邻接点是否存在
            while (w != -1) {
                //  判断该邻接点是否被访问过
                if (!isVisited[w]) {
                    //  输出当前节点
                    System.out.print(vertexLists.get(w) + " ");
                    //  将该邻接点标记为已访问
                    isVisited[w] = true;
                    //  将该邻接点入队
                    queue.add(w);
                }
                //  查找当前节点的下一个邻接点
                w = getNextNeighbor(u, w);
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来得晚一些也行

观众老爷,请赏~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值