1.深度优先搜索(Depth First Search)遍历相似于树的先根遍历,是树的先根遍历的推广。java
假设初始状态是图中全部的顶点不曾被访问,则深度优先搜索可从图中某个顶点V出发,访问此顶点,而后依次从v的未被访问的邻接点出发深度优先遍历图,至关于一个递归的过程,直到图中全部和v有路径相通的顶点都被访问到;node
若此时图中还有顶点未被访问,则选图中的一个不曾被访问的顶点作起始点,重复上述过程,直至图中全部顶点都被访问到为止。算法
2.如下图为例,作个简单的深度优先搜索遍历过程:数组
该图有v1,v2...到V9共9个顶点,假设从顶点V1开始出发进行搜索遍历,在访问了V1顶点以后,选择邻接点V2,由于V2不曾被访问,则以V2为起始点,进行深度优先搜索,(相似于迭代),此时V2的邻接点有3个,分别为V1,V4,V5,V2,选择未被访问的邻接点V4,而后会以V4为起始点,进行深度优先搜索,此时V4的邻接点为V2和V8,V2已经被访问,顶点V4选择不曾被访问的顶点V8,这时会以V8为起始点作优先搜索遍历,V8的邻接点是V4和V5,而V4已经被访问,因此V8选择不曾被访问的顶点V5,V5的邻接点都被访问了,则回到V8,V8的全部邻接点也被访问了,回到V4,v2,到达V1,此时V1会选择未被访问的顶点V3,而后会以V3为起始点进行深度优先搜索,V3会选择V6,而后以V6为起始顶点作深度优先搜索,V6选择未被访问的邻接点V9,而V9会选择未被访问的V7,而后以V7为起始点作深度优先搜索遍历,发现V7的邻接点都已被访问,则回到V9,V9的邻接点也已被访问 ,则回到V6,回到V3,V1,此时发现V1的邻接点已经所有被访问。并且图中其余顶点也已经被访问,全部的顶点都已经被访问,说明此次的深度有限搜素遍历已经所有完成。函数
由此获得的顶点访问的顺序为:code
V1->V2->V4->V8->V5->V3->V6->V9->V7递归
3.很显然,上述遍历的过程是一个递归的过程。为了在遍历中区分顶点是否已经被遍历,须要附设访问标志数组visited[0..n-1],n是指顶点的个数,其初值为false.一旦某个顶点被访问,其相应的份量值为true,visited[i]=true.it
4.代码附上:采用的是以邻接表的存储结构class
/** * 从第i个顶点出发递归深度优先遍历图 * @param i * @param visited */ public void DFS(int i, boolean[] visited) { VNode v = mVexs[i]; visited[i] = true; ENode node= v.firstEdge; System.out.println(i+"("+mVexs[i].data+")"); while(node!=null){ if(!visited[node.ivex]){ DFS(node.ivex,visited); } node=node.nextEdge; } } public void DFS() { boolean[] visisted = new boolean[mVexs.length]; //建立一个以顶点数为容量长度的布尔数组用来存取顶点数是否被访问的标志 //初始化顶点标志数组 for (int i = 0; i < mVexs.length; i++) { visisted[i] = false; } for (int i = 0; i < mVexs.length; i++) { if (!visisted[i]) { //对未访问的顶点调用DFS() DFS(i, visisted); } } }
5.算法复杂度搜索
分析上面的算法,在遍历图时,对图中的每一个顶点至多调用一次DFS函数,由于一旦某个顶点被标志为已被访问,就再也不从它出发进行深度优先搜索了。所以,遍历图的过程实质上是对每一个顶点查找其邻接点的过程。其耗费时间取决于图所采用的存储结构。
当用二维数组 表示邻接矩阵做图的存储结构时,查找每一个顶点的邻接点须要时间为O(n*n),n为顶点的个数。
而当以邻接表做图的存储结构时,查找邻接点的所需时间为O(e),其中e为无向图中边的数,或有向图中弧的个数。
由此,当以邻接表作存储结构时,深度优先搜索遍历图的时间复杂度为O(n+e)