Java数据结构——图的广度优先BFS

图的广度优先搜索(Broad First Search),类似于一个分层搜索的过程,广度优先遍历需要使用一个队列以保持访问过的结点的顺序,以便按这个顺序来访问这些结点的邻接结点。

一、什么是广度优先

就是尽可能一层一层找完,这一层找不到再找下一层。

二、思想
  1. 访问初始结点 v 并标记结点 v 为已访问。
  2. 结点 v 入队列
  3. 当队列非空时,继续执行,否则算法结束。
  4. 出队列,取得队头结点 u
  5. 查找结点 u 的第一个邻接结点 w
  6. 若结点 u 的邻接结点 w 不存在,则转到步骤 3;否则循环执行以下三个步骤:
    6.1 若结点 w 尚未被访问,则访问结点 w 并标记为已访问。
    6.2 结点 w 入队列
    6.3 查找结点 u 的继 w 邻接结点后的下一个邻接结点 w,转到步骤 6。

结合上面的例子分析一下步骤:

  1. 从A开始,输出A,标记A已访问。把A加入到队列,转到A这一层,再移除A。
  2. 在A这一层,找到A的第一个结点B,输出B,标记B已访问,把B加入到队列。
  3. 在A这一层,找到B的邻接结点C,输出C,标记C已访问,把C加入到队列。
  4. 在A这一层,找到C的邻接结点没有,转到B这一层,再从队列中移除B。
  5. 在B这一层,找到B的第一个结点A,A已被访问;找到A的邻接节点C,C已被访问;找到C的邻接节点D,输出D,标记D已访问,把D加入到队列。
  6. 在B这一层,找到D的邻接节点E,输出E,标记E已访问,把E加入到队列。
  7. 在B这一层,找到E的邻接节点,没有,转到C这一层,再从队列中移除C。
  8. 在C这一层,找到C的第一个结点A,A已被访问;找到A的邻接节点B,B已被访问;.....直到走到C这一层的尽头,转到D这一层,再从队列中移除D。
  9. 在D这一层,......直到走到C这一层的尽头,转到E这一层,再从队列中移除E。
  10. 在E这一层,......直到走到E这一层的尽头,列表为空,结束。
三、代码实现

这里面有一部分深度优先的代码(已经被注释掉了),深度优先看http://t.csdnimg.cn/F9Qa6

为什么重载了bfs方法呢?为了防止是非连通图。

package Graph;

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

public class Graph {
    private ArrayList<String> 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 vertex: Vertexs){
            graph.insertVertex(vertex);
        }

        //添加边
        graph.insertEdge(0,1,1);
        graph.insertEdge(0,2,1);
        graph.insertEdge(1,2,1);
        graph.insertEdge(1,3,1);
        graph.insertEdge(1,4,1);

        //显示邻接矩阵
        graph.showGraph();
//        System.out.println("深度优先");
//        graph.dfs();
        System.out.println();
        System.out.println("广度优先");
        graph.bfs();

    }

    //构造器
    public Graph(int n){
        edges=new int[n][n];
        vertexList=new ArrayList<String>(n);
        numOfEdges=0;
        isvisited=new boolean[5];
    }


    //得到第一个邻接节点的下标w
    public int getFirstNeighbor(int index){
        for(int j=0;j<vertexList.size();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 bfs(boolean[]isvisited,int i){
        int u; //这一行的结点
        int w; //邻接结点
        LinkedList<Integer> queue=new LinkedList<>();
        System.out.print(getValueByIndex(i)+"->");
        isvisited[i]=true;
        queue.addLast(i);
        while(!queue.isEmpty()){
            u=(Integer)queue.removeFirst();
            w=getFirstNeighbor(u);
            while(w!=-1){
                if(!isvisited[w]) {
                    System.out.print(getValueByIndex(w) + "->");
                    isvisited[w] = true;
                    queue.addLast(w);
                }
                w=getNextNeighbor(u,w);
            }
        }
    }

    public void bfs(){
        for(int i=0;i<getNumOfVertex();i++){
            if(!isvisited[i]) {
                bfs(isvisited, i);
            }
        }
    }


    /*
    //深度优先
    public void dfs(boolean []isvisited,int i){
        System.out.printf(getValueByIndex(i)+"->");
        isvisited[i]=true;
        int w =getFirstNeighbor(i);
        while(w!=-1){
            if(!isvisited[w]){
                dfs(isvisited,w);
            }
            w=getNextNeighbor(i,w);
        }
    }


    public void dfs(){
        isvisited=new boolean[vertexList.size()];
        for(int i=0;i<getNumOfVertex();i++){
            if(!isvisited[i]){
                dfs(isvisited,i);
            }
        }
    }

     */


    //图中常用的方法
    //返回节点个数
    public int getNumOfVertex(){
        return vertexList.size();
    }

    //返回边的个数
    public int getNumOfEdges(){
        return numOfEdges;
    }

    //数字对应的点 0->'A' 1->'B'
    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);
    }

    //添加边
    public void insertEdge(int v1,int v2,int weight){
        edges[v1][v2]=weight;
        edges[v2][v1]=weight;
        numOfEdges++;
    }
}

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值