横向遍历_Java数据结构和算法(四)图的广度优先遍历算法,附代码(BFS)

  上一篇文章跟大家讲了图的深度优先遍历算法,今天跟大家分享一下图的广度优先遍历,图的广度优先搜索(BFS)类似于一个分层搜索的过程,广度优先遍历需要使用一个队列用以保存访问过的结点的顺序,一边按照这个顺序来访问这些结点的邻接结点。

广度优先遍历算法步骤(伪代码):

  1. 访问初始结点v,并标记结点v为已访问

  2. 结点v进入队列(队列必须从尾部加入,从头部取出)

  3. 当队列非空时,继续执行,否则对该结点的算法结束

  4. 取得队列的头结点u,并出队列

  5. 查找结点u的第一个邻接结点w

  6. 若结点u的邻接结点不存在,则转到步骤3,否则循环以下三个步骤

    1)若结点w尚未被访问,则访问结点w并标记为已访问

    2)结点w入队列

    3)若结点w已经被访问,查找结点u的继w邻接结点之后的下一个邻接结点w,转到步骤6

 广度优先遍历与深度优先遍历类似,只不过遍历树匈奴一个是纵向的一个是横向的,因此所有方法均可以共用,代码如下,代码均为自己手敲:

/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */package graph;import java.util.ArrayList;import java.util.Arrays;import java.util.LinkedList;/** * * @author Administrator */public class Graph {    /**     * @param args the command line arguments     */    private ArrayList vertexList;   //存储结点集合    private int [][]edges;   //存储图对应的邻接矩阵    private int numOfEdges;  // 表示边的数目    private boolean[] isVisited;    public static void main(String[] args) {        // 测试代码        int n=5;  //结点个数        String Vertexs[] ={"A","B","C","D","E"};        //创建图对象        Graph graph = new Graph(n);        //循环添加节点        for(String vertexvalue: Vertexs){            graph.insertVertex(vertexvalue);        }        //添加边        graph.insertEdges(0, 1, 1);        graph.insertEdges(0, 2, 1);        graph.insertEdges(1, 2, 1);        graph.insertEdges(1, 3, 1);        graph.insertEdges(1, 4, 1);        //显示邻接矩阵        graph.showGraph();       System.out.println("深度遍历");        graph.dfs();        System.out.println(" ");        System.out.println("广度优先遍历");        graph.bfs();    }    //构造器    public Graph(int n){         //构造图需要知道该图有多少个结点        //初始化矩阵和vertexList        edges = new int[n][n];        vertexList =new ArrayList(n);         numOfEdges = 0;        isVisited = new boolean[5];    }    //得到第一个邻接结点的下标,如果存在就返回对应的下标,否则返回-1    public int getFirstNeighbor(int index){        for(int j=0;j            if(edges[index][j]>0){                return j;            }        }        return -1;    }    //根据前一个邻接结点的下标来获取下一个邻接结点    public int getNextNeighbor(int v1, int v2){        for(int j= v2+1 ;j < vertexList.size(); j++){            if(edges[v1][j]>0){                return j;            }        }        return -1;    }    //深度优先遍历算法    public void dfs(boolean[] isVisited, int i){        //首先访问该结点输出        System.out.print(getValueByIndex(i)+"->");        //将这个结点设置为已经访问        isVisited[i]=true;        //查找结点i的第一个邻接结点w        int w = getFirstNeighbor(i);        while(w!=-1){  //说明有邻接结点            if(isVisited[w]!=true){                dfs(isVisited,w);            }            //如果w结点已经被访问            w=getNextNeighbor(i,w);        }    }    //对dfs进行一个重载,遍历所有结点并进行dfs    public void dfs(){        isVisited = new boolean[5];        for(int i=0;i            if(isVisited[i]!=true){                dfs(isVisited,i);            }        }    }    //对一个结点进行广度遍历优先的方法    private void bfs(boolean[] isVisited,int i){        int u; //队列头结点对应的下标        int w; //邻接结点的下标        //队列,记录结点访问顺序        LinkedList queue = new LinkedList();        //访问该结点 并输出结点信息        System.out.print(getValueByIndex(i)+"->");        //标记为以访问        isVisited[i]=true;        //将结点加入队列        queue.addLast(i);        while(!queue.isEmpty()){            //取出队列的头结点下标            u=(Integer)queue.removeFirst();            //得到结点u的第一个邻接结点w            w=getFirstNeighbor(u);  //           System.out.println(w);            while(w!=-1){ //找到结点u的邻接结点                if(!isVisited[w]){                    System.out.print(getValueByIndex(w)+"->");                    //标记已经访问                    isVisited[w]=true;                    //入队列                    queue.addLast(w);                    //以u为前驱点,找w后面的邻接结点                }                    w=getNextNeighbor(u,w);  //                   System.out.println(w);                            }        }    }    //遍历所有的结点都进行广度优先搜索    public void bfs(){        isVisited = new boolean[5];         for(int i=0;i            if(!isVisited[i]){                bfs(isVisited,i);            }        }    }    //图中常用的方法    //返回插入结点的个数    public   int getNumOfVertex(){        return vertexList.size();    }     //得到边的数目    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 showGraph(){        for(int[] link :edges){            System.out.println(Arrays.toString(link));        }    }    //插入结点    public void insertVertex(String vertex){        vertexList.add(vertex);    }    //添加边    // v1  v2 表示点的下标    public void insertEdges(int v1, int v2,int weight){        edges[v1][v2]=weight;        edges[v2][v1]=weight;        numOfEdges++;   }}

  其中第100行到第143行,为BFS具体实现的代码,运行之后,结果如下图所示:

af8ab9ec1de57ccc04663510b1e7183f.png

 从控制台可以得出,深度优先与广度优先遍历对于同一个图来说,得到的结果是相同的,以上就是遍历图中结点的两种方法,谢谢大家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值