Java實現圖的遍歷(深搜與廣搜)



本文以鄰接矩陣作爲存儲結構,用Java實現圖的遍歷,話不多說,先給出的圖的結構,如下: 

1、深度優先搜索遍歷 
思想: 
沿着樹的深度遍歷樹的節點,儘可能深的搜索樹的分支。當節點v的所有邊都己被探尋過,搜索將回溯到發現節點v的那條邊的起始節點。這一過程一直進行到已發現從源節點可達的所有節點爲止。如果還存在未被發現的節點,則選擇其中一個作爲源節點並重復以上過程,整個進程反覆進行直到所有節點都被訪問爲止。(百度百科)

代碼如下:

package com.ds.graph;

public class DFSTraverse {
    // 構造圖的邊
    private int[][] edges = { { 0, 1, 0, 0, 0, 1, 0, 0, 0 },
            { 1, 0, 1, 0, 0, 0, 1, 0, 1 }, { 0, 1, 0, 1, 0, 0, 0, 0, 1 },
            { 0, 0, 1, 0, 1, 0, 1, 1, 1 }, { 0, 0, 0, 1, 0, 1, 0, 1, 0 },
            { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 1, 0, 1, 0, 1, 0, 1, 0 },
            { 0, 0, 0, 1, 1, 0, 1, 0, 0 }, { 0, 1, 1, 1, 0, 0, 0, 0, 0 } };
    // 構造圖的頂點
    private String[] vertexs = { "A", "B", "C", "D", "E", "F", "G", "H", "I" };
    // 記錄被訪問頂點
    private boolean[] verStatus;
    // 頂點個數
    private int vertexsNum = vertexs.length;

    public void DFSTra() {
        verStatus = new boolean[vertexsNum];
        for (int i = 0; i < vertexsNum; i++) {
            if (verStatus[i] == false) {
                DFS(i);
            }
        }
    }

    // 遞歸深搜
    private void DFS(int i) {
        System.out.print(vertexs[i] + " ");
        verStatus[i] = true;
        for (int j = firstAdjVex(i); j >= 0; j = nextAdjvex(i, j)) {
            if (!verStatus[j]) {
                DFS(j);
            }
        }
    }

    // 返回與i相連的第一個頂點
    private int firstAdjVex(int i) {
        for (int j = 0; j < vertexsNum; j++) {
            if (edges[i][j] > 0) {
                return j;
            }
        }
        return -1;
    }

    // 返回與i相連的下一個頂點
    private int nextAdjvex(int i, int k) {
        for (int j = (k + 1); j < vertexsNum; j++) {
            if (edges[i][j] == 1) {
                return j;
            }
        }
        return -1;
    }

    // 測試
    public static void main(String[] args) {
        new DFSTraverse().DFSTra();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

2、廣度優先搜索遍歷 
思想: 
從根節點開始,沿着樹的寬度、按照層次依次遍歷樹的節點;

代碼如下:

package com.ds.graph;

import java.util.LinkedList;
import java.util.Queue;

public class BFSTraverse_0100 {
    // 構造圖的邊
    private int[][] edges = { { 0, 1, 0, 0, 0, 1, 0, 0, 0 },
            { 1, 0, 1, 0, 0, 0, 1, 0, 1 }, { 0, 1, 0, 1, 0, 0, 0, 0, 1 },
            { 0, 0, 1, 0, 1, 0, 1, 1, 1 }, { 0, 0, 0, 1, 0, 1, 0, 1, 0 },
            { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 1, 0, 1, 0, 1, 0, 1, 0 },
            { 0, 0, 0, 1, 1, 0, 1, 0, 0 }, { 0, 1, 1, 1, 0, 0, 0, 0, 0 } };
    // 構造圖的頂點
    private String[] vertexs = { "A", "B", "C", "D", "E", "F", "G", "H", "I" };
    // 記錄被訪問頂點
    private boolean[] verStatus;
    // 頂點個數
    private int vertexsNum = vertexs.length;

    // 廣搜
    private void BFS() {
        verStatus = new boolean[vertexsNum];
        Queue<Integer> temp = new LinkedList<Integer>();
        for (int i = 0; i < vertexsNum; i++) {
            if (!verStatus[i]) {
                System.out.print(vertexs[i] + " ");
                verStatus[i] = true;
                temp.offer(i);
                while (!temp.isEmpty()) {
                    int j = temp.poll();
                    for (int k = firstAdjvex(j); k >= 0; k = nextAdjvex(j, k)) {
                        if (!verStatus[k]) {
                            System.out.print(vertexs[k] + " ");
                            verStatus[k] = true;
                            temp.offer(k);
                        }
                    }
                }
            }
        }
    }

    // 返回與i相連的第一個頂點
    private int firstAdjvex(int i) {
        for (int j = 0; j < vertexsNum; j++) {
            if (edges[i][j] > 0) {
                return j;
            }
        }
        return -1;
    }

    // 返回與i相連的下一個頂點
    private int nextAdjvex(int i, int k) {
        for (int j = (k + 1); j < vertexsNum; j++) {
            if (edges[i][j] > 0) {
                return j;
            }
        }
        return -1;
    }

    // 測試
    public static void main(String args[]) {
        new BFSTraverse_0100().BFS();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68



[java] view plain copy
  1. import java.util.*;  
  2.   
  3. /** 
  4.   *  這個例子是圖的遍歷的兩種方式 
  5.   *  通過它,使我來理解圖的遍歷  
  6.   *  Created on 2013-11-18 
  7.   *  @version 0.1 
  8.   */  
  9. public class DeptSearch  
  10. {  
  11.     public static void main(String args[]){  
  12.         //構造需要點對象  
  13.         NodeT a=new NodeT("a");  
  14.         NodeT b=new NodeT("b");  
  15.         NodeT c=new NodeT("c");  
  16.         NodeT d=new NodeT("d");  
  17.         NodeT e=new NodeT("e");  
  18.         NodeT f=new NodeT("f");  
  19.         NodeT g=new NodeT("g");  
  20.         NodeT h=new NodeT("h");  
  21.         ArcT ab=new ArcT(a,b);  
  22.         ArcT ac=new ArcT(a,c);  
  23.         ArcT ad=new ArcT(a,d);  
  24.         ArcT ah=new ArcT(a,h);  
  25.         ArcT bc=new ArcT(b,c);  
  26.         ArcT de=new ArcT(d,e);  
  27.         ArcT ef=new ArcT(e,f);  
  28.         ArcT eg=new ArcT(e,g);  
  29.         ArcT hg=new ArcT(h,g);  
  30.   
  31.         //建立它們的關係  
  32.         a.outgoing.add(ab);  
  33.         a.outgoing.add(ac);  
  34.         a.outgoing.add(ad);  
  35.         a.outgoing.add(ah);  
  36.         b.outgoing.add(bc);  
  37.         d.outgoing.add(de);  
  38.         e.outgoing.add(ef);  
  39.         e.outgoing.add(eg);  
  40.         h.outgoing.add(hg);  
  41.   
  42.         //構造本對象  
  43.         DeptSearch search=new DeptSearch();  
  44.           
  45.         //廣度遍歷  
  46.         System.out.println("廣度遍歷如下:");  
  47.         search.widthSearch(a);  
  48.   
  49.         //深度遍歷  
  50.         System.out.println("深度遍歷如下:");  
  51.         List<NodeT> visited=new ArrayList<NodeT>();  
  52.         search.deptFisrtSearch(a,visited);  
  53.           
  54.     }  
  55.       
  56.     /* 
  57.      * 深度排序的方法 
  58.      * 這個方法的方式:按一個節點,一直深入的找下去,直到它沒有節點爲止 
  59.      * cur  當前的元素 
  60.      * visited 訪問過的元素的集合 
  61.      */  
  62.     void deptFisrtSearch(NodeT cur,List<NodeT> visited){  
  63.         //被訪問過了,就不訪問,防止死循環  
  64.         if(visited.contains(cur)) return;  
  65.         visited.add(cur);  
  66.         System.out.println("這個遍歷的是:"+cur.word);  
  67.         for(int i=0;i<cur.outgoing.size();i++){  
  68.             //訪問本點的結束點  
  69.             deptFisrtSearch(cur.outgoing.get(i).end,visited);  
  70.         }  
  71.     }  
  72.   
  73.     /** 
  74.      * 廣度排序的方法 
  75.      * 這個方法的方式:按層次對圖進行訪問,先第一層,再第二層,依次類推 
  76.      * @param start 從哪個開始廣度排序 
  77.      */  
  78.     void widthSearch(NodeT start){  
  79.         //記錄所有訪問過的元素  
  80.         Set<NodeT> visited=new HashSet<NodeT>();  
  81.         //用隊列存放所有依次要訪問元素  
  82.         Queue<NodeT> q=new LinkedList<NodeT>();  
  83.         //把當前的元素加入到隊列尾  
  84.         q.offer(start);  
  85.           
  86.         while(!q.isEmpty()){  
  87.             NodeT cur=q.poll();  
  88.             //被訪問過了,就不訪問,防止死循環  
  89.             if(!visited.contains(cur)){  
  90.                 visited.add(cur);  
  91.                 System.out.println("查找的節點是:"+cur.word);  
  92.                 for(int i=0;i<cur.outgoing.size();i++){  
  93.                     //把它的下一層,加入到隊列中  
  94.                     q.offer(cur.outgoing.get(i).end);  
  95.                 }  
  96.             }  
  97.         }  
  98.     }  
  99.   
  100. }  
  101.   
  102. /** 
  103.   * 圖的點 
  104.   */  
  105. class NodeT  
  106. {  
  107.     /* 點的所有關係的集合 */  
  108.     List<ArcT> outgoing;  
  109.     //點的字母  
  110.     String word;  
  111.     public NodeT(String word){  
  112.         this.word=word;  
  113.         outgoing=new ArrayList<ArcT>();  
  114.     }  
  115. }  
  116.   
  117. /** 
  118.   * 單個圖點的關係 
  119.   */  
  120. class ArcT  
  121. {  
  122.     NodeT start,end;/* 開始點,結束點 */  
  123.     public ArcT(NodeT start,NodeT end){  
  124.         this.start=start;  
  125.         this.end=end;  
  126.     }  
  127. }  


 


發佈了164 篇原創文章 · 獲贊 26 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章