[數據結構]圖的DFS和BFS的兩種實現方式


深度優先搜索

深度優先搜索,我們以無向圖為例。

圖的深度優先搜索(Depth First Search),和樹的先序遍歷比較類似。

它的思想:假設初始狀態是圖中所有頂點均未被訪問,則從某個頂點v出發,首先訪問該頂點,然后依次從它的各個未被訪問的鄰接點出發深度優先搜索遍歷圖,直至圖中所有和v有路徑相通的頂點都被訪問到。 若此時尚有其他頂點未被訪問到,則另選一個未被訪問的頂點作起始點,重復上述過程,直至圖中所有頂點都被訪問到為止。

顯然,深度優先搜索是一個遞歸的過程。

鄰接矩陣DFS

package com.darrenchan.graph;

public class MatrixNDG {
    int size;//圖頂點個數
    char[] vertexs;//圖頂點名稱
    int[][] matrix;//圖關系矩陣

    public MatrixNDG(char[] vertexs, char[][] edges){
        size=vertexs.length;
        matrix=new int[size][size];//設定圖關系矩陣大小
        this.vertexs=vertexs;

        for(char[] c:edges){//設置矩陣值
            int p1 = getPosition(c[0]);//根據頂點名稱確定對應矩陣下標
            int p2 = getPosition(c[1]);

            matrix[p1][p2] = 1;//無向圖,在兩個對稱位置存儲
            matrix[p2][p1] = 1;
        }
    }

    //圖的遍歷輸出
    public void print(){
        for(int[] i:matrix){
            for(int j:i){
                System.out.print(j+" ");
            }
            System.out.println();
        }
    }

    //根據頂點名稱獲取對應的矩陣下標
    private int getPosition(char ch) {
        for(int i=0; i<vertexs.length; i++)
            if(vertexs[i]==ch)
                return i;
        return -1;
    }

    public static void main(String[] args) {
        char[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G','H','I','J','K'};
        char[][] edges = new char[][]{
                {'A', 'C'},
                {'A', 'D'},
                {'A', 'F'},
                {'B', 'C'},
                {'C', 'D'},
                {'E', 'G'},
                {'D', 'G'},
                {'I', 'J'},
                {'J', 'G'},
                {'E', 'H'},
                {'H', 'K'}};
        MatrixNDG pG = new MatrixNDG(vexs, edges);
        pG.print();
        pG.DFS();
    }

    public void DFS(){
        boolean[] beTraversed=new boolean[size];
        for(int i=0;i<size;i++){
            beTraversed[i]=false;
        }
        System.out.print(vertexs[0] + " ");
        beTraversed[0]=true;
        DFS(0,0,beTraversed);
    }

    private void DFS(int x,int y,boolean[] beTraversed){
        while(y<=size-1){
            if(matrix[x][y]!=0&beTraversed[y]==false){
                System.out.print(vertexs[y] + " ");
                beTraversed[y]=true;
                DFS(y,0,beTraversed);
            }
            y++;
        }
    }
}

鄰接表DFS

package com.darrenchan.graph;

public class ListNDG {
    Vertex[] vertexLists;//鄰接表數組
    int size;

    class Vertex{//鄰接表節點類,單鏈表數據結構
        char ch;
        Vertex next;

        Vertex(char ch){//初始化方法
            this.ch=ch;
        }
        void add(char ch){//加到鏈表尾
            Vertex node=this;
            while(node.next!=null){
                node=node.next;
            }
            node.next=new Vertex(ch);
        }
    }

    public ListNDG(char[] vertexs,char[][] edges){

        size=vertexs.length;
        this.vertexLists=new Vertex[size];//確定鄰接表大小
        //設置鄰接表每一個節點
        for(int i=0;i<size;i++){
            this.vertexLists[i]=new Vertex(vertexs[i]);
        }
        //存儲邊信息
        for(char[] c:edges){
            int p1=getPosition(c[0]);
            vertexLists[p1].add(c[1]);
            int p2=getPosition(c[1]);
            vertexLists[p2].add(c[0]);
        }

    }

    //跟據頂點名稱獲取鏈表下標
    private int getPosition(char ch) {
        for(int i=0; i<size; i++)
            if(vertexLists[i].ch==ch)
                return i;
        return -1;
    }

    //遍歷輸出鄰接表
    public void print(){
        for(int i=0;i<size;i++){
            Vertex temp=vertexLists[i];
            while(temp!=null){
                System.out.print(temp.ch+" ");
                temp=temp.next;
            }
            System.out.println();
        }
    }

    public static void main(String[] args){
        char[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G','H','I','J','K'};
        char[][] edges = new char[][]{
                {'A', 'C'},
                {'A', 'D'},
                {'A', 'F'},
                {'B', 'C'},
                {'C', 'D'},
                {'E', 'G'},
                {'D', 'G'},
                {'I', 'J'},
                {'J', 'G'},
                {'E', 'H'},
                {'H', 'K'}};

        ListNDG pG = new ListNDG(vexs, edges);
        pG.print();   // 打印圖
        pG.DFS();
    }

    public void DFS(){
        boolean[] beTraversed=new boolean[size];
        for(int i=0;i<size;i++){
            beTraversed[i]=false;
        }
        for (int i = 0; i < size; i++) {
            if (!beTraversed[i])
                DFS(beTraversed,vertexLists[i]);
        }

    }

    public void DFS(boolean[] beTraversed,Vertex temp){

        System.out.print(temp.ch + " ");
        beTraversed[getPosition(temp.ch)]=true;

        while(temp!=null){
            if(beTraversed[getPosition(temp.ch)]==false){
                DFS(beTraversed,vertexLists[getPosition(temp.ch)]);
            }
            temp=temp.next;
        }

    }
}

廣度優先搜索

廣度優先搜索,我們以有向圖為例。

廣度優先搜索算法(Breadth First Search),又稱為”寬度優先搜索”或”橫向優先搜索”,簡稱BFS。

它的思想是:從圖中某頂點v出發,在訪問了v之后依次訪問v的各個未曾訪問過的鄰接點,然后分別從這些鄰接點出發依次訪問它們的鄰接點,並使得“先被訪問的頂點的鄰接點先於后被訪問的頂點的鄰接點被訪問,直至圖中所有已被訪問的頂點的鄰接點都被訪問到。如果此時圖中尚有頂點未被訪問,則需要另選一個未曾被訪問過的頂點作為新的起始點,重復上述過程,直至圖中所有頂點都被訪問到為止。

換句話說,廣度優先搜索遍歷圖的過程是以v為起點,由近至遠,依次訪問和v有路徑相通且路徑長度為1,2…的頂點。

鄰接矩陣BFS

package com.darrenchan.graph;

import java.util.LinkedList;

public class MatrixDG {
    int size;
    char[] vertexs;
    int[][] matrix;

    public MatrixDG(char[] vertexs,char[][] edges){
        size=vertexs.length;
        matrix=new int[size][size];
        this.vertexs=vertexs;

        //和鄰接矩陣無向圖差別僅僅在這里
        for(char[] c:edges){
            int p1 = getPosition(c[0]);
            int p2 = getPosition(c[1]);

            matrix[p1][p2] = 1;
        }

    }

    public void print(){
        for(int[] i:matrix){
            for(int j:i){
                System.out.print(j+" ");
            }
            System.out.println();
        }
    }

    private int getPosition(char ch) {
        for(int i=0; i<vertexs.length; i++)
            if(vertexs[i]==ch)
                return i;
        return -1;
    }



    public static void main(String[] args) {
        char[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G','H','I','J','K'};
        char[][] edges = new char[][]{
                {'A', 'C'},
                {'A', 'D'},
                {'A', 'F'},
                {'B', 'C'},
                {'C', 'D'},
                {'E', 'G'},
                {'D', 'G'},
                {'I', 'J'},
                {'J', 'G'},
                {'E', 'H'},
                {'H', 'K'}};
        MatrixDG pG = new MatrixDG(vexs, edges);
        pG.print();
        pG.BFS();
    }

    public void BFS(){
        boolean[] beTraversed=new boolean[size];
        for(int i=0;i<size;i++){
            beTraversed[i]=false;
        }
        System.out.print(vertexs[0] + " ");
        beTraversed[0]=true;
        BFS(0,beTraversed);
    }

    public void BFS(int x,boolean[] beTraversed){
        LinkedList<Character> list=new LinkedList<Character>();
        int y=0;
        while(y<=size-1){
            if(matrix[x][y]!=0&beTraversed[y]==false){
                System.out.print(vertexs[y] + " ");
                beTraversed[y]=true;
                list.add(vertexs[y]);
            }
            y++;
        }
        while(!list.isEmpty()){
            char ch=list.pop();
            int t=getPosition(ch);
            BFS(t,beTraversed);
        }
    }

}

鄰接表BFS

package com.darrenchan.graph;

import java.util.LinkedList;

public class ListDG {
    Vertex[] vertexLists;
    int size;

    class Vertex{
        char ch;
        Vertex next;

        Vertex(char ch){
            this.ch=ch;
        }
        void add(char ch){
            Vertex node=this;
            while(node.next!=null){
                node=node.next;
            }
            node.next=new Vertex(ch);
        }


    }

    public ListDG(char[] vertexs,char[][] edges){

        size=vertexs.length;
        this.vertexLists=new Vertex[size];
        //設置鄰接表每一個節點
        for(int i=0;i<size;i++){
            this.vertexLists[i]=new Vertex(vertexs[i]);
        }
        //存儲邊信息
        //只有這里和無序圖不同
        for(char[] c:edges){
            int p=getPosition(c[0]);
            vertexLists[p].add(c[1]);
        }

    }

    private int getPosition(char ch) {
        for(int i=0; i<size; i++)
            if(vertexLists[i].ch==ch)
                return i;
        return -1;
    }

    public void print(){
        for(int i=0;i<size;i++){
            Vertex temp=vertexLists[i];
            while(temp!=null){
                System.out.print(temp.ch+" ");
                temp=temp.next;
            }
            System.out.println();
        }
    }

    public static void main(String[] args){
        char[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G','H','I','J','K'};
        char[][] edges = new char[][]{
                {'A', 'C'},
                {'A', 'D'},
                {'A', 'F'},
                {'B', 'C'},
                {'C', 'D'},
                {'E', 'G'},
                {'D', 'G'},
                {'I', 'J'},
                {'J', 'G'},
                {'E', 'H'},
                {'H', 'K'}};

        ListDG pG = new ListDG(vexs, edges);
        pG.print();   // 打印圖
        pG.BFS();
    }

    public void BFS(){
        boolean[] isTraversed=new boolean[size];
        for(int i=0;i<size;i++){
            isTraversed[i]=false;
        }
        System.out.print(vertexLists[0].ch + " ");
        isTraversed[0]=true;
        BFS(0,isTraversed);
    }

    public void BFS(int x,boolean[] isTraversed){
        Vertex temp=vertexLists[x];
        LinkedList<Vertex> list=new LinkedList<Vertex>();
        while(temp!=null){
            if(isTraversed[getPosition(temp.ch)]==false){
                System.out.print(temp.ch + " ");
                isTraversed[getPosition(temp.ch)]=true;
                list.add(temp);
            }
            temp=temp.next;
        }
        while(!list.isEmpty()){
            Vertex v=list.pop();
            int t=getPosition(v.ch);
            BFS(t,isTraversed);
        }
    }
}

 

參考:https://blog.csdn.net/picway/article/details/68483894


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM