無向圖的廣度優先遍歷和深度優先遍歷(簡易實現)

圖的遍歷就是從圖中某個頂點出發,按某種方法對圖中全部頂點訪問且僅訪問一次。
圖的遍歷算法是求解圖的連通性問題、拓撲排序和求關鍵路徑等算法的基礎,也能夠用做網頁的爬蟲技術,
深度優先遍歷(depth-first search):相似於樹的先根遍歷,是樹的先根遍歷的推廣,從一個圖節點去訪問它的鄰接節點,
                 知道沒有鄰接節點後再回溯,而後繼續向下訪問(通常用棧的方式來實現)
廣度優先遍歷(breadth-first search):遍歷相似於樹的層次遍歷,它是樹的按層遍歷的推廣(通常用隊列的方式實現)
 
在這個例子中,深度優先遍歷是最右邊的節點優先訪問
 
  1 package graph;
  2 
  3 import java.util.Arrays;
  4 import java.util.HashMap;
  5 import java.util.LinkedList;
  6 import java.util.List;
  7 import java.util.Map;
  8 import java.util.Queue;
  9 import java.util.Stack;
 10 
 11 
 12 public class Graph {
 13     //聲明一個map集合用來存放圖的結構
 14     private Map<String, List<String>> graphMap=new HashMap<String, List<String>>();
 15     //創建無向圖的模型
 16     //  圖結構以下
 17     //         1
 18     //      /   \
 19     //     2     3
 20     //    / \   / \
 21     //    4  5  6  7
 22     //     \ | / \ /
 23     //       8    9
 24     public void  initGraph() {
 25         /**
 26          * 初始化圖結構,將每一個圖節點爲key,它的相鄰節點以list爲value的形式存放到map中
 27          */
 28         graphMap.put("1",Arrays.asList("2","3"));
 29         graphMap.put("2",Arrays.asList("1","4","5"));
 30         graphMap.put("3",Arrays.asList("1","6","7"));
 31         graphMap.put("4",Arrays.asList("2","8"));
 32         graphMap.put("5",Arrays.asList("2","8"));
 33         graphMap.put("6",Arrays.asList("3","8","9"));
 34         graphMap.put("7",Arrays.asList("3","9"));
 35         graphMap.put("8",Arrays.asList("4","5","6"));
 36         graphMap.put("9",Arrays.asList("6","7"));
 37     }
 38     //用來記錄節點是否被訪問過
 39     private Map<String, Boolean> status=new HashMap<String,Boolean>();
 40     //建立一個隊列用來進行寬度優先遍歷
 41     private Queue<String> queue =new LinkedList<String>();
 42     public void BreadthFS(String startPoint) {
 43         //將圖的起始點入隊
 44         queue.offer(startPoint);
 45         status.put(startPoint, true);
 46         while(!queue.isEmpty()) {
 47             //將隊首的元素出隊
 48             String tempPoint =queue.poll();
 49             System.out.print(tempPoint+"-");
 50             //遍歷以後的節點,將其狀態改成false
 51             status.put(tempPoint, false);
 52             //遍歷該節點鄰接的節點
 53             for (String point : graphMap.get(tempPoint)) {
 54                 //若是該節點被訪問過,則不入隊
 55                 //getOrDefault:當集合中不存在該key,或者該key的值爲null時則默認值爲true
 56                 if(status.getOrDefault(point, true)){
 57                     //若是隊列中已經存在了該節點,則再也不次入隊
 58                     if(!queue.contains(point)) {
 59                         queue.offer(point);
 60                     }
 61                 }
 62             }
 63         }
 64     }
 65     public void depthFS(String startPoint) {
 66         //創建一個棧用來進行深度優先遍歷
 67         Stack<String> stack=new Stack<String>();
 68         //用來記錄棧中元素的狀態
 69         Map<String, Boolean> status=new HashMap<String,Boolean>();
 70         //將起始的點入棧
 71         stack.push(startPoint);
 72         while (!stack.isEmpty()) {
 73             //-----------顯示棧內的數據狀況----------------
 74             System.out.print("\t");
 75                 for (String string : stack) {
 76                     System.out.print(string);
 77                     if(!string.equals(stack.lastElement())){
 78                         System.out.print("->");
 79                     }
 80                 }
 81                 System.out.println();
 82             //---------------------------
 83                 String tempPoint =stack.pop();//出棧
 84             
 85             //出棧後的元素標記爲已遍歷(false)
 86             status.put(tempPoint, false);
 87             //打印出棧順序
 88             System.out.print(tempPoint);
 89             for (String point : graphMap.get(tempPoint)) {
 90                 //getOrDefault:當集合中不存在該key,或者該key的值爲null時則默認值爲true
 91                 if(status.getOrDefault(point, true)) {
 92                     //若是包含這個棧中沒有這個元素-->入棧
 93                     //有這個元素,先刪除棧中的該元素,再入棧。
 94                     if(!stack.contains(point)) {
 95                         stack.push(point);
 96                     }else {
 97                         stack.remove(point);
 98                         stack.push(point);
 99                     }
100                 }
101             }
102         }
103     }
104     //用遞歸來實現無向圖的深度優先遍歷
105     public void depthFSwithRecusive(String StartPoint) {
106         if(status.getOrDefault(StartPoint,true)) {
107             System.out.print(StartPoint+"-");
108             status.put(StartPoint, false);
109         }
110         for (String point : graphMap.get(StartPoint)) {
111             if(status.getOrDefault(point,true)) {
112                 depthFSwithRecusive(point);
113             }
114         }
115     }
116 }

測試代碼:java

 1 @org.junit.Test
 2     public void graphBFS() {
 3         Graph graph=new Graph();
 4         graph.initGraph();
 5         graph.BreadthFS("1");
 6     }
 7     @org.junit.Test
 8     public void graphDFS() {
 9         Graph graph=new Graph();
10         graph.initGraph();
11         graph.depthFS("1");
12     }

 

深度優先遍歷的運行結果:(最左邊爲 出棧順序,右邊是棧內信息的打印)算法

 

深度優先遍歷的運行結果:測試

相關文章
相關標籤/搜索