首页 > 代码库 > 深度优先搜索 && 广度优先搜索
深度优先搜索 && 广度优先搜索
类比二叉树先序遍历与图深度优先搜索
在引入图的深度优先搜索之前,为了更加容易理解.先考究一种特殊的图---二叉树的深度优先搜索算法---即二叉树的递归遍历方法.
二叉树的前序遍历算法:
void TreeWalk(node* root) { if(root) { visit(root); TreeWalk(root->left); TreeWalk(root->right); } }
对于二叉树来说,步骤如下:
1.如果root不为空,先访问root,
2再递归下降地访问root->left和root->right.
在二叉树中,与root邻接的结点只有left and right.所以,每次只需要递归下降访问这两个节点即可.
对于图来说,可以类比二叉树(特殊情况),总结出一般规律:
1先选定任意一个点vex做为生成树的根结点.访问该根点,
2再递归下降地访问与vex邻接的而且未被访问过的所有结点.
在图中,与vex邻接的结点是不像二叉树一样只有left 和 right,因为是不确定的,因此需要循环地查找判断哪些点邻接并且尚未被访问过.
伪代码:
void DFS(Graph& g,int vex) { Visit vex and Mark vex is visited; for w=FirstAdjacencyVertex to LastAdjacencyVertex(which is not visited before) DFS(g,w) }
//深度优先算法,可以形成一棵树 void DFS(Graph& g,int vex) { cout<<vex<<' '; visited[vex]=true;//is visited int w=FirstAdjVertex(g,vex); while(w>0) { DFS(g,w); w=NextAdjVertex(g,vex,w); } }
其中,FirstAdjVertex(g,vex)可以返回vex的第一个未被访问的邻接结点w.NextAdjVertex(g,vex,w)可以返回vex的下一个未被访问的邻接结点,在编号上在w之后.(小编号结点优先原则).
//找第一个未被访问过的邻接结点,找不到返回0 int FirstAdjVertex(Graph& g,int vex) { for(int i=1;i<=g.vnum;++i)//从点1开始找与vex邻接的第一个结点 { if(g.edge[vex][i]==1 && !visited[i]) return i; } return 0; } //找下一个未被访问过的邻接结点 int NextAdjVertex(Graph& g,int vex,int w) { for(int i=w;i<=g.vnum;++i)//从w开始,找下一个未被访问过的邻接结点 { if(g.edge[vex][i]==1 && !visited[i])//若i与vex邻接且i未访问过,下一次遍历,就从这个点往下. return i; } return 0;//点都从1开始,返回0则所以点已访问过 }
对于无向连通图或者强有向强连通图,可以调用DFS形成一棵深度优先搜索树.但是,对于非连通图或者非强连通图.需要在生成一棵树之后,继续寻找是否还存在未被访问到的点,在这些点上继续调用DFS,最终形成森林.
void DFS_traver(Graph& g) { for(int i=1;i<=g.vnum;++i) { if(!visited[i])//如果i结点未被访问过,形成森林 DFS(g,i); } }
图的广度优先遍历BFS算法是一个分层搜索的过程,和树的层序遍历算法类同,它也需要一个队列以保持遍历过的顶点顺序,以便按出队的顺序再去访问这些顶点的邻接顶点。
1.连通图的广度优先遍历算法思想。
(1)顶点v入队列。
(2)当队列非空时则继续执行,否则算法结束。
(3)出队列取得队头顶点v;访问顶点v并标记顶点v已被访问。
(4)查找顶点v的第一个邻接顶点col。
(5)若v的邻接顶点col未被访问过的,则col入队列。
(6)继续查找顶点v的另一个新的邻接顶点col,转到步骤(5)。直到顶点v的所有未被访问过的邻接点处理完。转到步骤(2)。
int visited[8]; void BFS(int edge[][8],int vex) { queue<int> q; //visited[vex] = 1; //标记已被访问过 q.push(vex); //初始化队列 while(!q.empty()) { vex=q.front(); q.pop(); //取出队头数据 if(!visited[vex]) { cout<<vex<<' '; visited[vex] = 1; //标记已被访问过 } for ( int j=0; j<8; ++j ) { if(edge[vex][j] == 1 && !visited[j] ) //邻接未被访问过的结点入队 { q.push(j); } } } } void BFS_traver(int g[][8]) { int i; for(i=0;i<8;i++) visited[i]=0; for(i=0;i<8;++i) { if(!visited[i]) { BFS(g,i); //如果i结点未被访问过,形成森林 } } }
这里使用了一个有八个顶点的图
深度优先搜索 && 广度优先搜索
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。