Bootstrap

图的深度优先搜索和广度优先搜索

一、深度优先搜索(DFS)
每次都在访问完当前节点后首先访问当前节点的第一个邻接节点,可以看出这是一个递归的过程。
深度优先遍历算法步骤:
1、访问初始尾结点v,并标记结点v已经访问
2、查找结点v的第一个领接结点
3、若w存在,则继续执行4,若w不存在,则回到第一步,将从v的下一个结点继续
4、若w未被访问,对w进行深度优先遍历递归(即把w当做另一个v,然后进行步骤123)
5、查找结点v的w邻接结点的写一个邻接结点,转到步骤3
具体问题分析:

 

A

B

C

D

E

A

0

1

1

0

0

B

1

0

1

1

1

C

1

1

0

0

0

D

0

1

0

0

0

E

0

1

0

0

0

// 说明

// 1表示能够直连,0表示不能直接连接

深度优先搜索过程:

A-B-C-D-E,A和B和C能够联通,联通为“1”;B和A、C、D、E联通;C和A、B联通;D和B联通,E和B联通。

A连接B,找到B后,B连接C,C联通不了别的节点,就再回到B,B联通D,B联通E。(找到哪个点就不变了,一条道走到黑)。

代码:

/得到第一个结点的下标
    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;
    }
    
    //深度优先遍历
    /* isVisited[] 记录结点是否访问的数组
     * i 第一次是0
     */
    public void dfs(boolean[] isVisited,int i){
        //首先访问该节点,输出
        System.out.print(getValueByIndex(i)+"->");
        isVisited[i]=true;
        int w=getfirstNeighbor(i);
        while(w!=-1){
            //说明有邻接结点
            if(!isVisited[w]){
                dfs(isVisited,w);
            }
            //如果该结点被访问
            w=getNextNeighbor(i,w);
        }
    }
    //重载dfs方法
    public void dfs(){
        isVisited=new boolean[vertexList.size()];
        //遍历所有的结点进行dfs回溯
        for(int i=0;i<vertexList.size();i++){
            if(!isVisited[i]){
                dfs(isVisited,i);
            }
        }
    }

二、图的广度优先遍历(BFS)

广度优先遍历基本思想类似于一个分层搜索的过程,需要使用一个队列以保持访问过的结点的顺序,方便按照这个顺序来访问这些结点的领接结点。

算法步骤:

1访问初始结点v并标记结点v已经访问

2结点v入队列

3当队列非空时,继续执行,否则算法就结束

4出队列,取得队头节点u

5查找节点u的第一个领接结点v

6若结点u的领接结点w不存在,则转移到步骤3,否则循环执行以下三个步骤

6.1若结点w尚未被访问,则访问结点w并标记已经访问

6.2结点w入队列

6.3查找结点u的继w领接结点后的下一个领接结点,转移到步骤6.

查找过程如下:

A找到B,再找B的后继结点C,A可以找到C,此时B在队列中,将B弹出,从B结点找,此时A结点已经被访问过,C也被访问过,此时D被访问到了,E也可以访问到.

也就是,B和C由A访问到,D和E由A结点访问到。 

//广度优先遍历
    public void bfs(boolean isVisited[],int i){
        int u; //表示队列的头结点对应下标
        int w; //邻接结点
        //队列,记录访问结点的顺序
        LinkedList queue=new LinkedList();
        //输出访问结点信息
        System.out.println(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.println(getValueByIndex(w)+"->");
                    //标记为已访问
                    isVisited[w]=true;
                    //入队
                    queue.addLast(w);
                }
                //以u为前驱点,找w后面的下一个结点
                w=getNextNeighbor(u,w);
            }
        }
    }
    
    //遍历所有的结点,都进行广度优先搜索
    public void bfs(){
        isVisited=new boolean[vertexList.size()];
        for(int i=0;i<vertexList.size();i++){
            if(!isVisited[i]){
                bfs(isVisited,i);
            }
        }
    }

get!

;