图的深度优先遍历及广度优先遍历

package Graph;

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

public class Graph {
    public static void main(String[] args) {
        int n = 5;
        Graph graph = new Graph(5);
        String [] vertex = {"A","B","C","D","E"};//--》[A, B, C, D, E]-->[0,1,2,3,4]
        for(String node : vertex){
            graph.add(node);
        }

        //加入边A-B\A-C\B-C\B-D\B-E
        graph.addEdges(0,1,1);
        graph.addEdges(0,2,1);
        graph.addEdges(1,2,1);
        graph.addEdges(1,3,1);
        graph.addEdges(1,4,1);

        //测试邻接矩阵的构建
        graph.showGraph();

        //测试深度优先遍历
        //System.out.println("深度优先遍历:");
        //graph.dfs();

        //测试广度优先
        System.out.println("广度优先遍历:");
        graph.bfs();
    }

    private ArrayList<String> vertexList;//图的结点
    private int [][] edges;//图的边,邻接矩阵
    private int numOfEdges;//边的数目
    private boolean [] isVisited;//记录结点是否被访问过

//构造函数
    public Graph(int n){
        //传入结点的个数
        vertexList = new ArrayList<>(n);
        edges = new int[n][n];
        isVisited = new boolean[n];
        numOfEdges = 0;//边的数目先初始化为0
    }

    //加入一个
    public void add(String vertex){
        vertexList.add(vertex);
    }

    //加入边,构建邻接矩阵
    //v1 v2对应结点在数组的下标
    public void addEdges(int v1, int v2, int weight){
        edges[v1][v2] = weight;
        edges[v2][v1] = weight;
        numOfEdges += 1;
    }

    //图中常用的方法
    public int getNumOfVertex(){
        return vertexList.size();
    }

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

    //返回下标对应的结点
    public String getValueByIndex(int i){
        return vertexList.get(i);
    }

    //返回边
    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 int getFirstNeighbour(int index){
        for(int j = 0; j < vertexList.size(); j++){
            if(edges[index][j] > 0){
                return j;
            }
        }
        return -1;//没有找到
    }

    //根据前一个邻接节点的下标,获取下一个邻接节点的下标-->获取当前结点的下一个邻接节点的下下个邻接结点
    public int getNextNeighbour(int v1, int v2){
        for(int j = v2 + 1; j < vertexList.size(); j++){
            if(edges[v1][j] > 0){
                return j;
            }
        }

        return -1;//没有找到
    }

    //深度遍历
    //i 第一次访问的结点
    public void dfs(boolean []isVisited, int i){
        //访问改节点
        if(i == vertexList.size() - 1){
            System.out.print(getValueByIndex(i));
        } else {
            System.out.print(getValueByIndex(i) + "->");
        }
        isVisited[i] = true;

        int w = getFirstNeighbour(i);
        //如果w存在
        while (w != -1){
            if( !isVisited[w]){
                dfs(isVisited,w);
            }
            //如果w 结点已经被访问过,去查找临街结点的下一个临接结点
            w = getNextNeighbour(i,w);
        }
    }

    //对dfs进行重载,因为如果不是连通图,有些结点没被访问
    public void dfs(){
        //遍历所有的结点
        for(int i = 0; i < vertexList.size(); i++){
            if(!isVisited[i])
            {
                dfs(isVisited,i);
            }
        }
    }

    //宽度优先遍历
    //需要使用一个队列来保存已经访问过的结点的顺序
    //以便按这个顺序来访问这些结点的邻接节点

    public void bfs(boolean []isVisited, int i){
        int u;//队列头的结点的下标
        int w;//邻接节点
        //队列,记录访问顺序LinkedList模仿队列
        LinkedList<Integer> queue = new LinkedList<>();

        if(i == vertexList.size() - 1){
            System.out.print(getValueByIndex(i));
        } else {
            System.out.print(getValueByIndex(i) + "->");
        }
        //标志已被访问
        isVisited[i] = true;

        //入队
        queue.addLast(i);

        //访问i 结点的所有邻接节点
        while (!queue.isEmpty()){
            u = queue.removeFirst();
            w = getFirstNeighbour(u);

            while (w != -1){
                if(!isVisited[w]){
                    if(w == vertexList.size() - 1){
                        System.out.print(getValueByIndex(w));
                    } else{
                        System.out.print(getValueByIndex(w) + "->");
                    }

                    isVisited[w] = true;
                    //访问该结点并入队
                    queue.addLast(w);
                }
                //如果已经访问过,则访问下一邻接节点
                w = getNextNeighbour(u,w);
            }
        }
    }

    //对广度优先进行重载,以便在遍历非连通图时
    public void bfs(){
        for(int i = 0; i < vertexList.size(); i++){
            if(!isVisited[i]){
                bfs(isVisited,i);
            }
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值