广度优先和深度优先

  1 package test;
  2 
  3 import java.util.ArrayList;
  4 import java.util.LinkedList;
  5 
  6 public class Graph {
  7     private int[][] edges;
  8     private ArrayList vertexList;
  9     private boolean[] isVisited;
 10     private int numVertex;
 11 
 12     public Graph(int n) {
 13         edges = new int[n][n];
 14         vertexList = new ArrayList(n);
 15         isVisited = new boolean[n];
 16         numVertex = n;




17 // 每个顶点初始化为false 18 for (int i = 0; i < n; i++) { 19 isVisited[i] = false; 20 } 21 } 22 23 public void insertVertex(String vertex) { 24 vertexList.add(vertex); 25 } 26 27 public void insertEdge(int v1, int v2, int weight) { 28 edges[v1][v2] = weight; 29 } 30 31 public void depthFirstSearch() { 32 for (int i = 0; i < numVertex; i++) { 33 if (!isVisited[i])// 如果某个点没访问的话,那么去遍历 34 { 35 depthFirstSearch(isVisited, i); 36 } 37 } 38 } 39 40 public int getFirstNeighbor(int index) { 41 for (int j = 0; j < numVertex; j++) { 42 if (edges[index][j] > 0) { 43 return j; 44 } 45 } 46 return -1;// 表示此点没有与之相邻的点 47 } 48 49 // 从v2开始检查,可以减少计算量 50 public int getNextNeighbor(int v1, int v2) { 51 for (int j = v2 + 1; j < numVertex; j++) { 52 if (edges[v1][j] > 0) { 53 return j; 54 } 55 } 56 return -1; 57 } 58 59 public void depthFirstSearch(boolean[] isVisited, int i) { 60 // 61 System.out.print(vertexList.get(i) + " "); 62 isVisited[i] = true; 63 int newStartNode = getFirstNeighbor(i); 64 while (newStartNode != -1) { 65 if (!isVisited[newStartNode])// 如果这个点没有被访问 66 { 67 depthFirstSearch(isVisited, newStartNode); 68 } 69 newStartNode = getNextNeighbor(i, newStartNode); 70 } 71 } 72 73 // 广度优先 74 public void broadFirstSearch() { 75 for (int i = 0; i < numVertex; i++) { 76 broadFirstSearch(isVisited, i); 77 } 78 } 79 80 private void broadFirstSearch(boolean[] isVisited, int i) { 81 int currentVisitedNode, adjacentCurrentVisitedNode; 82 LinkedList queue = new LinkedList(); 83 // 访问该节点 84 System.out.print(vertexList.get(i) + " "); 85 isVisited[i] = true; 86 // 节点入队列 87 queue.add(i); 88 while (!queue.isEmpty()) { 89 currentVisitedNode = ((Integer) queue.removeFirst()).intValue();// 移除队列的第一个元素,即头 90 adjacentCurrentVisitedNode = getFirstNeighbor(currentVisitedNode); 91 92 while (adjacentCurrentVisitedNode != -1) { 93 if (!isVisited[adjacentCurrentVisitedNode]) { 94 // 访问该节点 95 System.out.print(vertexList.get(adjacentCurrentVisitedNode) + " "); 96 // 标记该节点 97 isVisited[adjacentCurrentVisitedNode] = true; 98 // 入队列 99 queue.addLast(adjacentCurrentVisitedNode); 100 } 101 // 寻找下一个邻接节点 102 adjacentCurrentVisitedNode = getNextNeighbor(currentVisitedNode, adjacentCurrentVisitedNode); 103 } 104 } 105 106 } 107 }
 1 package test;
 2 
 3 public class TestSearch {
 4     public static void main(String args[]) {
 5 
 6         String labels[] = { "1", "2", "3", "4", "5" };// 结点的标识
 7         int n = labels.length;
 8         Graph graph = new Graph(n);
 9         for (String label : labels) {
10             graph.insertVertex(label);// 插入结点
11         }
12         // 插入四条边
13         graph.insertEdge(0, 1, 1);
14         graph.insertEdge(0, 2, 1);
15         graph.insertEdge(1, 3, 1);
16         graph.insertEdge(1, 4, 1);
17 
18         System.out.println("深度优先搜索序列为:");
19         graph.depthFirstSearch();
20         
21          System.out.println();
22          System.out.println("广度优先搜索序列为:");
23          graph.broadFirstSearch();
24     }
25 }

运行结果如下:

深度优先搜索序列为:
1 2 4 5 3
广度优先搜索序列为:
1 2 3 4 5

 

 

 

总的来说,BFS多用于寻找最短路径的问题,DFS多用于快速发现底部节点。

 

DFS的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底。

DFS适合此类题目:给定初始状态跟目标状态,要求判断从初始状态到目标状态是否有解。

 

深度与广度的比较:

我们搜索一个图是按照树的层次来搜索的。

我们假设一个节点衍生出来的相邻节点平均的个数是N个,那么当起点开始搜索的时候,队列有一个节点,当起点拿出来后,把它相邻的节点放进去,那么队列就有N个节点,当下一层

的搜索中再加入元素到队列的时候,节点数达到了N/2,你可以想象,一旦N是一个比较大的数的时候,这个树的层次又比较深,那这个队列就需要很大的内存空间了。

于是广度优先搜索的缺点出来了:在树的层次较深或子节点数较多的情况下,消耗内存十分严重。广度优先搜索适用于节点的子节点数量不多,并且树的层次不会太深的情况。

 

那么深度优先就可以克服这个缺点,因为每次搜的过程,每一层只需维护一个节点。但回过头想想,广度优先能够找到最短路径,那深度优先能否找到呢?深度优先的方法是一条路走到黑,

那显然无法知道这条路是不是最短的,所以你还得继续走别的路去判断是否是最短路?

于是深度优先搜索的缺点也出来了:难以寻找最优解,只能寻找有解。其优点就是内存消耗小,克服了刚刚说的广度优先搜索的缺点。

 

 

递归版深度优先

 1 public class DFSTest
 2 {
 3     private int vertexNum;//顶点个数
 4     private int[][] adjacent;//邻接矩阵
 5     private boolean[] isVisited;//顶点是否经过的标记
 6     private char[] nodeName;//顶点名称
 7     
 8     //图的初始化
 9     public DFSTest(int n)
10     {
11         vertexNum=n;
12         adjacent=new int[vertexNum][vertexNum];
13         isVisited=new boolean[vertexNum];
14         for (int i=0;i<vertexNum;i++)
15         {
16             for (int j=0;j<vertexNum;j++)
17             {
18                 adjacent[i][j]=0;
19             }
20         }
21         
22         for (int k=0;k<n;k++)
23         {
24             isVisited[k]=false;
25         }
26     }
27     
28     public void setNodeName(char[] a)
29     {
30         nodeName=new char[vertexNum];
31         for (int i=0;i<a.length;i++)
32         {
33             nodeName[i]=a[i];
34         }
35     }
36     
37     //无向图
38     public void setAdjacent(int i,int j)
39     {
40         adjacent[i][j]=1;
41         adjacent[j][i]=1;
42     }
43     
44     
45     
46     //遍历
47     public void dfsTraverse()
48     {
49         for (int i=0;i<vertexNum;i++)
50         {
51             if (isVisited[i]==false)
52             {
53                 dfs(i);
54             }
55         }
56     }
57     
58     public void dfs(int n)
59     {
60         isVisited[n]=true;//
61         //可利用每次遍历的节点的个数来判断此路是否有解
62         System.out.println(nodeName[n]);
63         for (int i=0;i<vertexNum;i++)
64         {
65             if (adjacent[n][i]==1&&isVisited[i]==false)
66             {
67                 dfs(i);
68             }
69         }
70     }
71     
72     
73     public static void main(String[] args)
74     {
75         int n=4;//表示图中顶点的个数
76         DFSTest dfsTest=new DFSTest(n);
77         //给顶点赋名字
78         char[] name={'A','B','C','D'};
79         dfsTest.setNodeName(name);
80         //加边
81         dfsTest.setAdjacent(0, 1);
82         dfsTest.setAdjacent(1, 3);
83         dfsTest.setAdjacent(2, 3);
84         
85         dfsTest.dfsTraverse();
86         
87     }
88 }

 

posted @ 2016-03-23 20:33  笑哼  阅读(974)  评论(0编辑  收藏  举报