图的深度优先搜索与广度优先搜索(JAVA)

图的存储结构

一、邻接矩阵 (Adjacency Matrix)表示(数组表示法)

基本思想:
用一个一维数组存储图中顶点的信息,用一个二维数组(称为邻接矩阵)存储图中各顶点之间的邻接关系。假设图G=(V,E)有n个顶点,则邻接矩阵是一个n×n的方阵,定义为:
在这里插入图片描述
无向图的邻接矩阵:
在这里插入图片描述
在这里插入图片描述
存储结构特点:主对角线为 0 且一定是对称矩阵;

有向图的邻接矩阵:
在这里插入图片描述
在这里插入图片描述
假设图G有n个顶点e条边,则该图的存储需求为O(n+n^2) = O(n^2) ,与边的条数e无关。

存储结构的建立----算法实现的步骤:

  1. 确定图的顶点个数n和边数e;
  2. 输入顶点信息存储在一维数组vertex中;
  3. 初始化邻接矩阵;
  4. 依次输入每条边存储在邻接矩阵edge中;
    4.1 输入边依附的两个顶点的序号i, j;
    4.2 将邻接矩阵的第i行第j列的元素值置为1;
    4.3 将邻接矩阵的第j行第i列的元素值置为1。
class MatrixGraph{
    
    
    private ArrayList<String> vertexList; //存储顶点集合
    private int[][] edges; //存储图对应的邻结矩阵
    private int numOfEdges; //表示边的数目
    //定义给数组boolean[], 记录某个结点是否被访问
    private boolean[] isVisited;
    //构造器
    public MatrixGraph(int n) {
    
    
        //初始化矩阵和vertexList
        edges = new int[n][n];
        vertexList = new ArrayList<String>(n);
        numOfEdges = 0;

    }
    //图中常用的方法
    //返回结点的个数
    public int getNumOfVertex() {
    
     return vertexList.size(); }
    //显示图对应的矩阵
    public void showGraph() {
    
    
        for(int[] link : edges) {
    
    
            System.err.println(Arrays.toString(link));
        }
    }
    //得到边的数目
    public int getNumOfEdges() {
    
     return numOfEdges; }
    //返回结点i(下标)对应的数据 0->"A" 1->"B" 2->"C"
    public String getValueByIndex(int i) {
    
     return vertexList.get(i); }
    //返回v1和v2的权值
    public int getWeight(int v1, int v2) {
    
     return edges[v1][v2]; }
    //插入结点
    public void insertVertex(String vertex) {
    
     vertexList.add(vertex); }
    //添加边
    /**
     *
     * @param v1 表示点的下标即使第几个顶点  "A"-"B" "A"->0 "B"->1
     * @param v2 第二个顶点对应的下标
     * @param weight 表示权值
     */
    public void insertEdge(int v1, int v2, int weight) {
    
    
        edges[v1][v2] = weight;
        edges[v2][v1] = weight;
        numOfEdges++;
    }
}

二、邻接表( Adjacency List )表示

无向图的邻接表:

  • 对于无向图的每个顶点vi,将所有与vi相邻的顶点链成一个单链表,称为顶点vi的边表(顶点vi的邻接表);
  • 再把所有边表的指针和顶点信息的一维数组构成顶点表。

在这里插入图片描述
有向图的邻接表—正邻接表

  • 对于有向图的每个顶点vi,将邻接于vi的所有顶点链成一个单链表,称为顶点vi的出边表;
  • 再把所有出边表的指针和顶点信息的一维数组构成顶点表.

在这里插入图片描述
有向图的邻接表----逆邻接表

  • 对于有向图的每个顶点vi,将邻接到vi的所有顶点链成一个单链表,称为顶点vi的入边表;
  • 再把所有入边表的指针和存储顶点信息的一维数组构成顶点表。
    在这里插入图片描述

邻接表存储结构建立算法实现的步骤:

  1. 确定图的顶点个数和边的个数;
  2. 建立顶点表:
    2.1 输入顶点信息;
    2.2 初始化该顶点的边表;
  3. 依次输入边的信息并存储在边表中;
    3.1 输入边所依附的两个顶点的序号tail和head和权值w;
    3.2 生成邻接点序号为head的边表结点p;
    3.3 设置边表结点p;
    3.4 将结点p插入到第tail个边表的头部;
//无向图
class ListGraph{
    
    
    private VertexNode[] vexlist ;
    private int numOfEdges; //表示边的数目
    public ListGraph(int n) {
    
    
        vexlist = new VertexNode[n];
    }

    //图中常用的方法
    //返回结点的个数
    public int getNumOfVertex() {
    
     return vexlist.length; }
    //得到边的数目
    public int getNumOfEdges() {
    
     return numOfEdges; }
    //返回结点i(下标)对应的数据 0->"A" 1->"B" 2->"C"
    public String getValueByIndex(int i) {
    
     return vexlist[i].getVertex(); }
    //返回v1和v2的权值
    public int getWeight(int v1, int v2) {
    
    
        EdgeNode edge = vexlist[v1].getFirstedge();
        while (edge !=null){
    
    
            if (edge.getAdjvex() ==v2){
    
    
                return edge.getCost();
            }
            edge =edge.getNext();
        }
        return 0;
    }
  //显示图
    public void showGraph(){
    
    
        for (VertexNode vex:vexlist){
    
    
            System.out.print(vex.getVertex());
            EdgeNode edge = vex.getFirstedge();
            while (edge !=null){
    
    
                System.out.print("->"+vexlist[edge.getAdjvex()].getVertex());
                edge = edge.getNext();
            }
            System.out.println();
        }
    }
    //插入结点
    public void insertVertex(int index,String vertex) {
    
     
        vexlist[index] = new VertexNode(vertex);
    }

    //添加边
    public void insertEdge(int v1, int v2, int weight) {
    
    
        if(vexlist[v1] ==null || vexlist[v2] ==null){
    
    
            System.out.println("未加入顶点!!");
            return;
        }
        if (vexlist[v1].getFirstedge() ==null){
    
    
            vexlist[v1].setFirstedge(new EdgeNode(v2,weight));
        }else {
    
    //找到边表的末尾,在末尾添加
            EdgeNode edge =  vexlist[v1].getFirstedge();
            while (edge.getNext() !=null){
    
    
                edge = edge.getNext();
            }
            edge.setNext(new EdgeNode(v2,weight));
        }
        //无向图,两个顶点都要添加
        if (vexlist[v2].getFirstedge() ==null){
    
    
            vexlist[v2].setFirstedge(new EdgeNode(v1,weight));
        }else {
    
    //找到边表的末尾,在末尾添加
            EdgeNode edge =  vexlist[v2].getFirstedge();
            while (edge.getNext() !=null){
    
    
                edge = edge.getNext();
            }
            edge.setNext(new EdgeNode(v1,weight));
        }
        
    }
    
}
//顶点表结点
class VertexNode{
    
    
    private String vertex; //顶点数据域
    private EdgeNode  firstedge;//边链表头指针
    public VertexNode(String vertex) {
    
     this.vertex = vertex; }
    public String getVertex() {
    
     return vertex; }
    public void setVertex(String vertex) {
    
     this.vertex = vertex; }
    public EdgeNode getFirstedge() {
    
     return firstedge; }
    public void setFirstedge(EdgeNode firstedge) {
    
     this.firstedge = firstedge; }
}

//边表结点
class EdgeNode{
    
    
    private int adjvex; //邻接点域(下标)
    private int cost; //边上的权值
    private EdgeNode next; //下一边链接指针
    public EdgeNode(int adjvex, int cost) {
    
    
        this.adjvex = adjvex;
        this.cost = cost;
    }
    public int getAdjvex() {
    
     return adjvex; }
    public void setAdjvex(int adjvex) {
    
     this.adjvex = adjvex; }
    public int getCost() {
    
     return cost; }
    public void setCost(int cost) {
    
     this.cost = cost; }
    public EdgeNode getNext() {
    
     return next; }
    public void setNext(EdgeNode next) {
    
     this.next = next; }
}

图的存储结构的比较——邻接矩阵和邻接表
在这里插入图片描述

深度优先搜索(Depth-First-Search)

----类似于树结构的先序遍历

设图G的初态是所有顶点都“未访问过(False)”,在G中任选一个顶点 v 为初始出发点(源点),则深度优先搜索可定义为:

  1. 首先访问出发点 v,并将其标记为“访问过 (True) ”;
  2. 然后,从 v 出发,依次考察与 v 相邻(邻接于或邻接到v)的顶点 w ;若 w “未访问过(False)”,则以 w 为新的出发点递归地进行深度优先搜索,直到图中所有与源点 v 有路径相通的顶点(亦称从源点可到达的顶点)均被访问为止;(从源点出发的一次先深搜索)
  3. 若此时图中仍有未被访问过的顶点,则另选一个“未访问过”的顶点作为新的搜索起点,重复上述过程,直到图中所有顶点都被访问过为止。

从一个顶点出发的一次深度优先遍历算法:
实现步骤:

  1. 所有顶点标记为未访问visited[v]={0,…};
  2. 访问顶点v; visited[v]=1;
  3. w=顶点v的第一个邻接点;
  4. while (w存在)
    4.1 if (w未被访问)
         从顶点w出发递归地执行该算法;
    4.2 w=顶点v的下一个邻接点;

邻接矩阵的深度优先代码实现

  
    //深度优先遍历算法
    //i 第一次就是 0
    private void dfs(boolean[] isVisited, int i) {
    
    
        //首先我们访问该结点,输出
        System.out.print(getValueByIndex(i) + "->");
        //将结点设置为已经访问
        isVisited[i] = true;
        for(int j = 0; j < vertexList.size(); j++) {
    
    //遍历与该节点相邻的点
            if(edges[i][j] > 0 &&!isVisited[j]) {
    
    //与i相邻的点且改点没被访问过
                dfs(isVisited, j);
            }
        }
    }

    //对dfs 进行一个重载, 遍历我们所有的结点,并进行 dfs
    public void dfs() {
    
    
        isVisited = new boolean[vertexList.size()];
        //遍历所有的结点,进行dfs[回溯]
        for(int i = 0; i < getNumOfVertex(); i++) {
    
    
            if(!isVisited[i] ) {
    
    
                dfs(isVisited, i);
            }
        }
    }

邻接表的深度优先代码实现

 //图的搜素遍历
    //深度优先遍历算法
    private void dfs(boolean[] isVisited, int i) {
    
    
        //首先我们访问该结点,输出
        System.out.print(getValueByIndex(i) + "->");
        //将结点设置为已经访问
        isVisited[i] = true;
        EdgeNode edgeNode = vexlist[i].getFirstedge();
        while (edgeNode != null){
    
    //遍历与该节点相邻的点
            if(!isVisited[edgeNode.getAdjvex()]){
    
    
                dfs(isVisited, edgeNode.getAdjvex());
            }
            edgeNode = edgeNode.getNext();
        }
    }

    //对dfs 进行一个重载, 遍历我们所有的结点,并进行 dfs
    public void dfs() {
    
    
        isVisited = new boolean[vexlist.length];
        //遍历所有的结点,进行dfs[回溯]
        for(int i = 0; i < getNumOfVertex(); i++) {
    
    
            if(!isVisited[i] ) {
    
    
                dfs(isVisited, i);
            }
        }
        System.out.println();
    }

广度优先搜索(Breadth-First-Search)

—类似于树的层序遍历
设图G的初态是所有顶点都“未访问过(False)”,在G中任选一个顶点 v 为源点,则广度优先搜索可定义为:

  1. 首先访问出发点 v,并将其标记为“访问过 (True)”;
  2. 接着依次访问所有与 v 相邻的顶点w1,w2…wt;
  3. 然后依次访问与w1,w2… wt相邻的所有未访问的顶点;
  4. 依次类推,直至图中所有与源点v有路相通的顶点都已访问过为止; (从源点出发的一次先广搜索)
  5. 此时,从 v 开始的搜索结束,若G是连通的,则遍历完成;否则在G中另选一个尚未访问的顶点作为新源点,继续上述搜索过程,直到G中的所有顶点均已访问为止。

从一个顶点出发的一次广度优先遍历算法:
实现步骤:

  1. 初始化队列Q;
  2. 访问顶点v; visited [v]=1; 顶点v入队Q;
  3. while (队列Q非空)
    3.1 v=队列Q的队头元素出队;
    3.2 w=顶点v的第一个邻接点;
    3.3 while (w存在) //访问v的所有邻接点
          3.3.1 如果w 未被访问,则访问顶点w; visited[w]=1; 顶点w入队列Q;
          3.3.2 w=顶点v的下一个邻接点;

邻接矩阵的广度优先代码实现


    //对一个结点进行广度优先遍历的方法
    private void bfs(boolean[] isVisited, int i) {
    
    
        int u ; // 表示队列的头结点对应下标
        int w ; // 邻接结点w
        //队列,记录结点访问的顺序
        LinkedList queue = new LinkedList();
        //访问结点,输出结点信息
        System.out.print(getValueByIndex(i) + "=>");
        //标记为已访问
        isVisited[i] = true;
        //将结点加入队列
        queue.addLast(i);

        while( !queue.isEmpty()) {
    
    
            //取出队列的头结点下标
            u = (Integer)queue.removeFirst();
            for( w = 0; w < vertexList.size(); w++) {
    
    //遍历寻找该节点相邻的点
                if(edges[u][w] > 0 &&!isVisited[w]) {
    
    //与i相邻的点且改点没被访问过
                    System.out.print( getValueByIndex(w)+ "=>");
                    //标记已经访问
                    isVisited[w] = true;
                    queue.addLast(w);//加入队列
                }
            }

        }

    }

    //遍历所有的结点,都进行广度优先搜索
    public void bfs() {
    
    
        isVisited = new boolean[vertexList.size()];
        for(int i = 0; i < getNumOfVertex(); i++) {
    
    
            if(!isVisited[i]) {
    
    
                bfs(isVisited, i);
            }
        }
    }

邻接表的广度优先代码实现

    //对一个结点进行广度优先遍历的方法
    private void bfs(boolean[] isVisited, int i) {
    
    
        int u; // 表示队列的头结点对应下标
        int w; // 邻接结点w
        //队列,记录结点访问的顺序
        LinkedList queue = new LinkedList();
        //访问结点,输出结点信息
        System.out.print(getValueByIndex(i) + "->");
        //标记为已访问
        isVisited[i] = true;
        //将结点加入队列
        queue.addLast(i);
        while( !queue.isEmpty()) {
    
    
            //取出队列的头结点下标
            u = (Integer)queue.removeFirst();
            EdgeNode edgeNode = vexlist[u].getFirstedge();
            while (edgeNode !=null){
    
    //遍历寻找该节点相邻的点
                if (!isVisited[edgeNode.getAdjvex()]) {
    
    //与i相邻的点且改点没被访问过
                    System.out.print( getValueByIndex(edgeNode.getAdjvex())+ "->");
                    //标记已经访问
                    isVisited[edgeNode.getAdjvex()] = true;
                    queue.addLast(edgeNode.getAdjvex());//加入队列
                }
                edgeNode = edgeNode.getNext();
            }
        }

    }
    //遍历所有的结点,都进行广度优先搜索
    public void bfs() {
    
    
        isVisited = new boolean[vexlist.length];
        for(int i = 0; i < getNumOfVertex(); i++) {
    
    
            if(!isVisited[i]) {
    
    
                bfs(isVisited, i);
            }
        }
        System.out.println();
    }

图的存储与搜索完整代码

邻接矩阵实现代码

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

/**
 * @anthor longzx
 * @create 2021 02 09 21:37
 * @Description
 **/
public class MatrixGraphDemo {
    
    
    public static void main(String[] args) {
    
    
        //测试一把图是否创建ok
        int n = 8;  //结点的个数
        //String Vertexs[] = {"A", "B", "C", "D", "E"};
        String Vertexs[] = {
    
    "0","1", "2", "3", "4", "5", "6", "7"};
        //创建图对象
        MatrixGraph graph = new MatrixGraph(n);
        //循环的添加顶点
        for(String vertex: Vertexs) {
    
    
            graph.insertVertex(vertex);
        }
        //更新边的关系
        graph.insertEdge(0, 1, 1);
        graph.insertEdge(0, 2, 1);
        graph.insertEdge(1, 3, 1);
        graph.insertEdge(1, 4, 1);
        graph.insertEdge(3, 7, 1);
        graph.insertEdge(4, 7, 1);
        graph.insertEdge(2, 5, 1);
        graph.insertEdge(2, 6, 1);
        graph.insertEdge(5, 6, 1);
        //显示一把邻结矩阵
        graph.showGraph();
        //测试一把,我们的dfs遍历是否ok
        System.out.println("深度遍历");
        graph.dfs(); // A->B->C->D->E [1->2->4->8->5->3->6->7]
        System.out.println("广度优先!");
        graph.bfs(); // A->B->C->D-E [1->2->3->4->5->6->7->8]

    }
}
class MatrixGraph{
    
    
    private ArrayList<String> vertexList; //存储顶点集合
    private int[][] edges; //存储图对应的邻结矩阵
    private int numOfEdges; //表示边的数目
    //定义给数组boolean[], 记录某个结点是否被访问
    private boolean[] isVisited;
    //构造器
    public MatrixGraph(int n) {
    
    
        //初始化矩阵和vertexList
        edges = new int[n][n];
        vertexList = new ArrayList<String>(n);
        numOfEdges = 0;

    }
    //图中常用的方法
    //返回结点的个数
    public int getNumOfVertex() {
    
     return vertexList.size(); }
    //显示图对应的矩阵
    public void showGraph() {
    
    
        for(int[] link : edges) {
    
    
            System.err.println(Arrays.toString(link));
        }
    }
    //得到边的数目
    public int getNumOfEdges() {
    
     return numOfEdges; }
    //返回结点i(下标)对应的数据 0->"A" 1->"B" 2->"C"
    public String getValueByIndex(int i) {
    
     return vertexList.get(i); }
    //返回v1和v2的权值
    public int getWeight(int v1, int v2) {
    
     return edges[v1][v2]; }
    //插入结点
    public void insertVertex(String vertex) {
    
     vertexList.add(vertex); }
    //添加边
    /**
     *
     * @param v1 表示点的下标即使第几个顶点  "A"-"B" "A"->0 "B"->1
     * @param v2 第二个顶点对应的下标
     * @param weight 表示权值
     */
    public void insertEdge(int v1, int v2, int weight) {
    
    
        edges[v1][v2] = weight;
        edges[v2][v1] = weight;
        numOfEdges++;
    }


    //图的搜素遍历

    //深度优先遍历算法
    //i 第一次就是 0
    private void dfs(boolean[] isVisited, int i) {
    
    
        //首先我们访问该结点,输出
        System.out.print(getValueByIndex(i) + "->");
        //将结点设置为已经访问
        isVisited[i] = true;
        for(int j = 0; j < vertexList.size(); j++) {
    
    //遍历与该节点相邻的点
            if(edges[i][j] > 0 &&!isVisited[j]) {
    
    //与i相邻的点且改点没被访问过
                dfs(isVisited, j);
            }
        }
    }

    //对dfs 进行一个重载, 遍历我们所有的结点,并进行 dfs
    public void dfs() {
    
    
        isVisited = new boolean[vertexList.size()];
        //遍历所有的结点,进行dfs[回溯]
        for(int i = 0; i < getNumOfVertex(); i++) {
    
    
            if(!isVisited[i] ) {
    
    
                dfs(isVisited, i);
            }
        }
        System.out.println();
    }


    //对一个结点进行广度优先遍历的方法
    private void bfs(boolean[] isVisited, int i) {
    
    
        int u ; // 表示队列的头结点对应下标
        int w ; // 邻接结点w
        //队列,记录结点访问的顺序
        LinkedList queue = new LinkedList();
        //访问结点,输出结点信息
        System.out.print(getValueByIndex(i) + "->");
        //标记为已访问
        isVisited[i] = true;
        //将结点加入队列
        queue.addLast(i);

        while( !queue.isEmpty()) {
    
    
            //取出队列的头结点下标
            u = (Integer)queue.removeFirst();
            for( w = 0; w < vertexList.size(); w++) {
    
    //遍历寻找该节点相邻的点
                if(edges[u][w] > 0 &&!isVisited[w]) {
    
    //与i相邻的点且改点没被访问过
                    System.out.print( getValueByIndex(w)+ "->");
                    //标记已经访问
                    isVisited[w] = true;
                    queue.addLast(w);//加入队列
                }
            }

        }

    }

    //遍历所有的结点,都进行广度优先搜索
    public void bfs() {
    
    
        isVisited = new boolean[vertexList.size()];
        for(int i = 0; i < getNumOfVertex(); i++) {
    
    
            if(!isVisited[i]) {
    
    
                bfs(isVisited, i);
            }
        }
        System.out.println();
    }
}

邻接表实现代码

import java.util.LinkedList;

/**
 * @anthor longzx
 * @create 2021 02 09 23:59
 * @Description
 **/
public class ListGraphDemo {
    
    

    public static void main(String[] args) {
    
    
        //测试一把图是否创建ok
        int n = 8;  //结点的个数
        //String Vertexs[] = {"A", "B", "C", "D", "E"};
        String Vertexs[] = {
    
    "0","1", "2", "3", "4", "5", "6", "7"};
        //创建图对象
        ListGraph graph = new ListGraph(n);
        //循环的添加顶点
        for(int i =0 ;i < Vertexs.length;i++) {
    
    
            graph.insertVertex(i,Vertexs[i]);
        }
        //更新边的关系
        graph.insertEdge(0, 1, 1);
        graph.insertEdge(0, 2, 1);
        graph.insertEdge(1, 3, 1);
        graph.insertEdge(1, 4, 1);
        graph.insertEdge(3, 7, 1);
        graph.insertEdge(4, 7, 1);
        graph.insertEdge(2, 5, 1);
        graph.insertEdge(2, 6, 1);
        graph.insertEdge(5, 6, 1);
        //显示一把邻结表
        graph.showGraph();
        System.out.println("深度遍历");
        graph.dfs(); // A->B->C->D->E [1->2->4->8->5->3->6->7]
        System.out.println("广度优先!");
        graph.bfs(); // A->B->C->D-E [1->2->3->4->5->6->7->8]
    }

}

//无向图
class ListGraph{
    
    
    private VertexNode[] vexlist ;//存储顶点的数组
    private int numOfEdges; //表示边的数目
    //定义给数组boolean[], 记录某个结点是否被访问
    private boolean[] isVisited;
    public ListGraph(int n) {
    
    
        vexlist = new VertexNode[n];
    }

    //图中常用的方法
    //返回结点的个数
    public int getNumOfVertex() {
    
     return vexlist.length; }
    //得到边的数目
    public int getNumOfEdges() {
    
     return numOfEdges; }
    //返回结点i(下标)对应的数据 0->"A" 1->"B" 2->"C"
    public String getValueByIndex(int i) {
    
     return vexlist[i].getVertex(); }
    //返回v1和v2的权值
    public int getWeight(int v1, int v2) {
    
    
        EdgeNode edge = vexlist[v1].getFirstedge();
        while (edge !=null){
    
    
            if (edge.getAdjvex() ==v2){
    
    
                return edge.getCost();
            }
            edge =edge.getNext();
        }
        return 0;
    }
    //显示图
    public void showGraph(){
    
    
        for (VertexNode vex:vexlist){
    
    
            System.out.print(vex.getVertex());
            EdgeNode edge = vex.getFirstedge();
            while (edge !=null){
    
    
                System.out.print("->"+vexlist[edge.getAdjvex()].getVertex());
                edge = edge.getNext();
            }
            System.out.println();
        }
    }

    //插入结点
    public void insertVertex(int index,String vertex) {
    
    
        vexlist[index] = new VertexNode(vertex);
    }

    //添加边
    public void insertEdge(int v1, int v2, int weight) {
    
    
        if(vexlist[v1] ==null || vexlist[v2] ==null){
    
    
            System.out.println("未加入顶点!!");
            return;
        }
        if (vexlist[v1].getFirstedge() ==null){
    
    
            vexlist[v1].setFirstedge(new EdgeNode(v2,weight));
        }else {
    
    //找到边表的末尾,在末尾添加
            EdgeNode edge =  vexlist[v1].getFirstedge();
            while (edge.getNext() !=null){
    
    
                edge = edge.getNext();
            }
            edge.setNext(new EdgeNode(v2,weight));
        }
        //无向图,两个顶点都要添加
        if (vexlist[v2].getFirstedge() ==null){
    
    
            vexlist[v2].setFirstedge(new EdgeNode(v1,weight));
        }else {
    
    //找到边表的末尾,在末尾添加
            EdgeNode edge =  vexlist[v2].getFirstedge();
            while (edge.getNext() !=null){
    
    
                edge = edge.getNext();
            }
            edge.setNext(new EdgeNode(v1,weight));
        }

    }

    //图的搜素遍历
    //深度优先遍历算法
    private void dfs(boolean[] isVisited, int i) {
    
    
        //首先我们访问该结点,输出
        System.out.print(getValueByIndex(i) + "->");
        //将结点设置为已经访问
        isVisited[i] = true;
        EdgeNode edgeNode = vexlist[i].getFirstedge();
        while (edgeNode != null){
    
    //遍历与该节点相邻的点
            if(!isVisited[edgeNode.getAdjvex()]){
    
    
                dfs(isVisited, edgeNode.getAdjvex());
            }
            edgeNode = edgeNode.getNext();
        }
    }

    //对dfs 进行一个重载, 遍历我们所有的结点,并进行 dfs
    public void dfs() {
    
    
        isVisited = new boolean[vexlist.length];
        //遍历所有的结点,进行dfs[回溯]
        for(int i = 0; i < getNumOfVertex(); i++) {
    
    
            if(!isVisited[i] ) {
    
    
                dfs(isVisited, i);
            }
        }
        System.out.println();
    }


    //对一个结点进行广度优先遍历的方法
    private void bfs(boolean[] isVisited, int i) {
    
    
        int u; // 表示队列的头结点对应下标
        int w; // 邻接结点w
        //队列,记录结点访问的顺序
        LinkedList queue = new LinkedList();
        //访问结点,输出结点信息
        System.out.print(getValueByIndex(i) + "->");
        //标记为已访问
        isVisited[i] = true;
        //将结点加入队列
        queue.addLast(i);
        while( !queue.isEmpty()) {
    
    
            //取出队列的头结点下标
            u = (Integer)queue.removeFirst();
            EdgeNode edgeNode = vexlist[u].getFirstedge();
            while (edgeNode !=null){
    
    //遍历寻找该节点相邻的点
                if (!isVisited[edgeNode.getAdjvex()]) {
    
    //与i相邻的点且改点没被访问过
                    System.out.print( getValueByIndex(edgeNode.getAdjvex())+ "->");
                    //标记已经访问
                    isVisited[edgeNode.getAdjvex()] = true;
                    queue.addLast(edgeNode.getAdjvex());//加入队列
                }
                edgeNode = edgeNode.getNext();
            }
        }

    }
    //遍历所有的结点,都进行广度优先搜索
    public void bfs() {
    
    
        isVisited = new boolean[vexlist.length];
        for(int i = 0; i < getNumOfVertex(); i++) {
    
    
            if(!isVisited[i]) {
    
    
                bfs(isVisited, i);
            }
        }
        System.out.println();
    }

    }
//顶点表结点
class VertexNode{
    
    
    private String vertex; //顶点数据域
    private EdgeNode  firstedge;//边链表头指针
    public VertexNode(String vertex) {
    
     this.vertex = vertex; }
    public String getVertex() {
    
     return vertex; }
    public void setVertex(String vertex) {
    
     this.vertex = vertex; }
    public EdgeNode getFirstedge() {
    
     return firstedge; }
    public void setFirstedge(EdgeNode firstedge) {
    
     this.firstedge = firstedge; }
}

//边表结点
class EdgeNode{
    
    
    private int adjvex; //邻接点域(下标)
    private int cost; //边上的权值
    private EdgeNode next; //下一边链接指针
    public EdgeNode(int adjvex, int cost) {
    
    
        this.adjvex = adjvex;
        this.cost = cost;
    }
    public int getAdjvex() {
    
     return adjvex; }
    public void setAdjvex(int adjvex) {
    
     this.adjvex = adjvex; }
    public int getCost() {
    
     return cost; }
    public void setCost(int cost) {
    
     this.cost = cost; }
    public EdgeNode getNext() {
    
     return next; }
    public void setNext(EdgeNode next) {
    
     this.next = next; }
}

猜你喜欢

转载自blog.csdn.net/qq_41784749/article/details/113775698
今日推荐