圖的鄰接矩陣表示方式及深度、廣度優(yōu)先算法的實(shí)現(xiàn)

圖的存儲(chǔ)結(jié)構(gòu)(鄰接矩陣方式)

此圖為帶權(quán)無(wú)向圖

public class MyGraph {
    
    private ArrayList<Object> vertexList;       //存放頂點(diǎn)的數(shù)組
    private int[][] edges;              //鄰接矩陣,存放邊集
    private int numofEdges;         //邊數(shù)
    private static final int INF = 65535;       //權(quán)值為65535時(shí)表示不可達(dá)
    private boolean[] visited;      //用于深度、廣度遍歷時(shí)頂點(diǎn)是否已被訪問(wèn)的標(biāo)志
    
    public MyGraph(int n) {
        vertexList = new    ArrayList<>(n); //根據(jù)傳入的頂點(diǎn)數(shù)構(gòu)造頂點(diǎn)數(shù)組
        edges = new int[n][n];                  //構(gòu)造對(duì)應(yīng)的鄰接矩陣
        numofEdges  = 0;
        visited = new boolean[n];
        //初始化鄰接矩陣
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                if (i == j) {
                    edges[i][j] = 0;
                }else {
                    edges[i][j] = INF;
                }
            }
        }
    }
    
    //獲取頂點(diǎn)個(gè)數(shù)
    public int getNumOfVertex() {
        return vertexList.size();
    }
    
    //獲取邊數(shù)
    public int getNumofEdges() {
        return numofEdges;
    }
    
    //打印鄰接矩陣
    public void printEdges() {
        for(int i = 0; i < vertexList.size(); i++) {
            for(int j =0; j < vertexList.size(); j++) {
                if (j == vertexList.size() - 1) {
                    System.out.println(edges[i][j]);
                }else {
                    System.out.print(edges[i][j]+" ");
                }
            }
        }
    }
    
    //獲取頂點(diǎn)n的值
    public Object getValueByIndex(int n) {
        return vertexList.get(n);
    }
    
    //獲取邊n1-n2的權(quán)值
    public int getWeight(int n1, int n2) {
        return edges[n1][n2];
    }
    
    //插入結(jié)點(diǎn)
    public void insertVertex(Object vertex) {
        vertexList.add(vertexList.size(),vertex);
    }
    
    //插入頂點(diǎn)以及設(shè)置權(quán)值
    public void insertEdge(int n1, int n2, int weight) {
        edges[n1][n2] = weight;
        //該圖為無(wú)向圖,所以矩陣關(guān)于對(duì)角線對(duì)稱
        edges[n2][n1] = weight;
        numofEdges++;
    }
    
    //刪除邊
    public void deleteEdge(int n1, int n2) {
        edges[n1][n2] = INF;
        //無(wú)向圖刪除邊時(shí)矩陣依舊對(duì)稱
        edges[n2][n1] = INF;
        numofEdges--;
    }
}

測(cè)試類
測(cè)試圖如圖所示:


圖片.png

測(cè)試程序如下:

        //頂點(diǎn)數(shù)為4
        int n = 4;
        String[] vertex = {"A","B","C","D"};
        MyGraph graph = new MyGraph(n);
        for (String string : vertex) {
            graph.insertVertex(string);
        }
        graph.insertEdge(0, 1, 3);
        graph.insertEdge(0, 2, 8);
        graph.insertEdge(0, 3,10);
        graph.insertEdge(1, 2, 6);
        
        System.out.println("結(jié)點(diǎn)數(shù):"+graph.getNumOfVertex());
        System.out.println("邊數(shù):"+graph.getNumofEdges());
        System.out.println("刪除前的鄰接矩陣:");
        graph.printEdges();
        
        graph.deleteEdge(1, 2);
        System.out.println("刪除邊<B,C>后:");
        System.out.println("結(jié)點(diǎn)個(gè)數(shù)為:"+graph.getNumOfVertex());
        System.out.println("邊數(shù)為:"+graph.getNumofEdges());
        System.out.println("刪除后的鄰接矩陣:");
        graph.printEdges();

測(cè)試結(jié)果:


圖片.png

遍歷算法

測(cè)試圖(由于權(quán)值不影響遍歷結(jié)果,所以不標(biāo)注):


圖片.png

深度優(yōu)先

    //鄰接矩陣的深度遍歷操作
    public void DFSTraverse(MyGraph graph) {
        for (int i = 0; i < graph.getNumOfVertex(); i++) {
            visited[i] = false;
        }
        for( int i = 0; i < graph.getNumOfVertex(); i++) {
            //對(duì)未訪問(wèn)過(guò)的結(jié)點(diǎn)調(diào)用DFS,若是連通圖,只會(huì)執(zhí)行一次,非連通圖的話有多少個(gè)子圖則會(huì)調(diào)用多少次
            if (!visited[i]) {
                DFS(graph, i);
            }
        }
    }
    
    //鄰接矩陣的深度優(yōu)先遞歸算法
    public void DFS(MyGraph graph, int i) {
        //設(shè)置訪問(wèn)標(biāo)志位為true
        visited[i] = true;
        System.out.print(getValueByIndex(i)+" ");
        for(int j = 0; j < graph.getNumOfVertex(); j++) {
            if (edges[i][j] != 0 && edges[i][j] != INF && !visited[j] ) {
                //對(duì)未訪問(wèn)的鄰接結(jié)點(diǎn)遞歸調(diào)用
                DFS(graph, j);
            }
        }
    }

廣度優(yōu)先

    //鄰接矩陣的廣度遍歷算法
    public void BFSTraverse(MyGraph graph) {
        int i,j;
        //初始化訪問(wèn)標(biāo)志矩陣
        for(i = 0; i < graph.getNumOfVertex(); i++) {
            visited[i] = false;
        }
        //使用linkedList模擬隊(duì)列的功能
        LinkedList<Integer> queue  = new LinkedList<>();
        for(i = 0; i < graph.getNumOfVertex(); i++) {
            //該圖為非連通圖時(shí),第一次廣度遍歷完后還有結(jié)點(diǎn)未被訪問(wèn)時(shí)會(huì)再次進(jìn)入這個(gè)分支
            //該圖為連通圖時(shí),該分支只會(huì)執(zhí)行一次,因?yàn)閳?zhí)行一次后所有的結(jié)點(diǎn)都被訪問(wèn)到了
            if (!visited[i]) {
                visited[i] = true;
                System.out.print(getValueByIndex(i)+" ");
                //將結(jié)點(diǎn)添加到隊(duì)尾
                queue.addLast(i);
                while(!queue.isEmpty()) {
                    //移除隊(duì)頭元素并將其賦值給i
                    i = ((Integer)queue.removeFirst()).intValue();
                    for(j = 0; j < graph.getNumOfVertex(); j++) {
                        if (edges[i][j] != 0 && edges[i][j] != INF && !visited[j] ) {
                            visited[j] = true;
                            System.out.print(getValueByIndex(j)+" ");
                            queue.addLast(j);
                        }
                    }
                }
            }
        }
    }

廣度優(yōu)先各結(jié)點(diǎn)在隊(duì)列中的情況如下

圖片.png

測(cè)試程序:

public class GraphTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //頂點(diǎn)數(shù)為4
        int n = 9;
        String[] vertex = {"A","B","C","D","E","F","G","H","I"};
        MyGraph graph = new MyGraph(n);
        for (String string : vertex) {
            graph.insertVertex(string);
        }
        graph.insertEdge(0, 1, 3);
        graph.insertEdge(0, 2, 8);
        graph.insertEdge(1, 3,10);
        graph.insertEdge(1, 4, 3);
        graph.insertEdge(2, 5, 3);
        graph.insertEdge(2, 6, 3);
        graph.insertEdge(3, 7, 3);
        graph.insertEdge(7, 8, 3);
        
        System.out.println("深度優(yōu)先遍歷結(jié)果:");
        graph.DFSTraverse(graph);
        System.out.println("\n廣度優(yōu)先遍歷:");
        graph.BFSTraverse(graph);
    }

}

測(cè)試結(jié)果:


圖片.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容