无向图的广度优先遍历和深度优先遍历(简易实现)

图的遍历就是从图中某个顶点出发,按某种方法对图中所有顶点访问且仅访问一次。
图的遍历算法是求解图的连通性问题、拓扑排序和求关键路径等算法的基础,也可以用作网页的爬虫技术,
深度优先遍历(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 }

测试代码:

 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     }

 

深度优先遍历的运行结果:(最左边为 出栈顺序,右边是栈内信息的打印)

 

深度优先遍历的运行结果:

 

 

 

posted on 2019-10-15 10:25  Not_Leave_Regrets  阅读(3014)  评论(0编辑  收藏  举报

导航