数据结构与算法之 图的深度优先和广度优先

图(无向图)的生成及深度优先遍历,及广度优先遍历

图的广度和深度优先遍历 用如下图来解决
在这里插入图片描述

图的创建:

java代码:

class Graph{
    private int edgesNum;     //边数
    private char [] vertexs;  //顶点
    private int [][] weight; //描述两边是否联通

    public Graph(int edgesNum){
        vertexs= new char[edgesNum];
        weight= new int[edgesNum][edgesNum];
    }


    public int getEdgesNum() {
        return edgesNum;
    }

    public void setEdgesNum(int edgesNum) {
        this.edgesNum = edgesNum;
    }

    public char[] getVertexs() {
        return vertexs;
    }

    public void setVertexs(char[] vertexs) {
        this.vertexs = vertexs;
    }

    public int[][] getWeight() {
        return weight;
    }

    public void setWeight(int[][] weight) {
        this.weight = weight;
    }
}
通过客户端传入参数给 operategraph对象,进行初始化

在这里插入图片描述

客户端代码 vertexs 描述顶点
二位邻接矩阵表示对边的描述,例如 a[0][0]=0 表示A 和 A相连 0 表示连不通,1表示能连通
       char []vertexs = {'A','B','C','D','E'};
        int[][] weight ={
                {0,1,1,0,0},
                {1,0,1,1,1},
                {1,1,0,0,0},
                {0,1,0,0,0},
                {0,1,0,0,0}
        };
OperateGraph 对图的各种操作’

OperateGraph类的代码

//图的操作类
class OperateGraph{
    private Graph graph;
    private boolean []isVisited;

    public OperateGraph(Graph graph) {
        this.graph = graph;
    }
    public void createGraph(char[] vertexs,int [][] weight){
        graph.setVertexs(vertexs);
        graph.setWeight(weight);

    }
    public void showWeight(){
        for (int i=0;i<graph.getWeight().length;i++){
            for(int j=0;j<graph.getWeight()[i].length;j++){
                System.out.printf("%d\t", graph.getWeight()[i][j]);
            }
            System.out.println();
        }
    }
    public void bfs(){
        this.isVisited = new boolean[this.graph.getVertexs().length];
        for(int j=0;j<this.graph.getVertexs().length;j++){
            if(isVisited[j] == false){
                bfs(isVisited,j); // 对每一个节点进行试探,看有没有被访问
            }
        }
    }
    //图的广度优先遍历
    public void bfs(boolean[] isVisited,int i){
        //首先打印首先要遍历的节点
        System.out.println(this.graph.getVertexs()[i]);
        //打印后该节点已经访问,标记 为true
        isVisited[i] = true;
        //将此节点放入栈
        Stack<Integer> stack = new Stack<>();
        stack.add(i);
        while(!stack.isEmpty()){ //退出遍历节点的
            int cur = stack.pop();
            int w = this.getFirstIndex(cur);
            //持续输出遍历节点的下一个相邻节点,直到找不到退出循环
            while (w!=-1){
                if(isVisited[w]==false){
                    System.out.println(this.graph.getVertexs()[w]);
                    isVisited[w] = true;
                    //入栈
                    stack.add(w);
                }
                //如果第一个相邻节点已经被访问,则访问当前节点的下一个邻接节点
              w=getNextIndex(i,w);
            }

        }
    }
    //此时只是遍历完一个节点
    public void dfs(boolean []isVisited,int i){ // 从那开始深度优先遍历
        int length =this.graph.getVertexs().length;
        char [] ver = this.graph.getVertexs();

        System.out.println(this.graph.getVertexs()[i]);
        isVisited[i] = true;
        //先得到第一个邻接节点下标
        int  FirstNerbor = this.getFirstIndex(i);
        while(FirstNerbor!=-1){
            //如果还没有访问,则开始递归访问
            if(isVisited[FirstNerbor]==false){
                dfs(isVisited,FirstNerbor);
            }
            //如果已经访问过了,则访问下一个邻接点
            FirstNerbor = getNextIndex(i,FirstNerbor);
        }
    }

    public void dfs(){
        this.isVisited = new boolean[this.graph.getVertexs().length];

        //遍历所有节点
        for(int i=0;i<this.graph.getVertexs().length;i++){
            if(this.isVisited[i]==false) {
                dfs(this.isVisited, i);
            }
        }
    }
    //得到下一个邻接节点
    public int getNextIndex(int h1,int h2){
        int index=-1;
        for(int j=h2+1;j<this.graph.getVertexs().length;j++){
            if(this.graph.getWeight()[h1][j]!=0){
                index = j;
                break;
            }
        }
        return index;
    }
    //得到第一个最近相邻节点下标
    public int getFirstIndex(int index){
        int nextIndex =-1;
        for(int j=0;j<this.graph.getVertexs().length;j++){
            if(this.graph.getWeight()[index][j]>0){
                nextIndex = j;
                break;
            }
        }
        return nextIndex;
    }
//得到该节点的当前下标
    public int getCurrentIndex(char ch) {
        int realIndex = -1;
       for(int i=0;i<this.graph.getVertexs().length;i++){

         if(ch==this.graph.getVertexs()[i]){
             realIndex = i;
         }
       }
       return realIndex;
    }
    }
最终运行结果如图

在这里插入图片描述
难点在于:深度和广度遍历的思想维度不一样,因此实现不一样
深度优先遍历的思路
1.访问初始节点v,并标记该节点已被访问
2.查找节点v的第一个邻接接节点w
3.若w存在,则执行4,如果不存在,则回到第一步,将从v的下一个结点出发
4若w未被访问,对w进行深度优先遍历递归(即把w当作v,进行123步)
5若w已被访问,则对该邻接节点的下一个邻接节点,转到步骤3

广度优先遍历思路:类似与一个分层搜索的过程,广度优先搜索遍历需要使用一个队列(或栈)以保持访问过节点顺序,已遍按这个顺序来访问这些节点的邻接节点
1.访问初始结点v并标记为已访问,
2节点入栈(队列)
3,如果栈不为空 while循环继续执行,否则算法结束
4出栈,取得该节点
5查找结点的第一个节点w
6.1若不存在,则转到步骤三
6.2若节点存在,且节点的邻接节点未被访问,则打印该节点,入栈
6.3若节点存在,且节点的邻接节点已被访问,则访问该节点的下一个邻接点,转到6.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值