DFS&BFS算法总结(1)

DFS&BFS算法总结

图论:

n图论中的图是由若干给定的点及连接两点的线所构成的图形,这种图形通常用来描述某些事物之间的某种特定关系,用点代表事物,用连接两点的线表示相应两个事物间具有这种关系。 例如:四色猜想、格尼斯宝七桥问题、拓扑理论……

图的搜索是说在给定一些点,这些点之间存在某种关系,按照这种关系,构造成一个图。从一个起始点出发,把所有和这个点存在这种关系的点全部找出来的过程就是搜索。

BFS– 广度优先搜索

BFS在访问了起始顶点A之后,由A出发,依次访问A的各个未被访问过的邻接顶点B,D,…, C, 然后再顺序访问B,D, …, C 的所有还未被访问过的邻接顶点。再从这些访问过的顶点出发,再访问它们的所有还未被访问过的邻接顶点,…如此做下去,直到图中所有顶点都被访问到为止。广度优先搜索是一种分层的搜索过程,每向前走一步可能访问一批顶点。


BFS 的代码分析
void BFS(){
	int queue[N];//按照顺序储存被处理的点
	int parent[N];//记录被处理的点的父亲节点
	int top;
	int i, j, k;
	top = 0;
	queue[top++] = 初始点;
                parent[初始点] = -1;
	标记初始点;
	for(i = 0; i < top; i++){ //队列中还有未处理点
		j = 队列中下一个处理点;
		for(j的所有邻接点){
			if(该邻接点未被标记){
				queue[top++] = 邻接点;
                                                                 parent[邻接点] = j;
				标记该邻接点;
			}
		}
	}
	//此时队列中的点就是所有要找的点
}

BFS 的另一种应用

假设图的每条边的权值都是1,因为BFS是分层进行的,所以,从起点到达同一层点的路经距离应该是相同的,如果在图中标记一个起点和一个终点,从起点出发,用BFS逐层向终点靠近,那么当到达终点时,会形成一条路径,那么这条路径必定是这两点的最短路经。

BFS求最短路径

int BFS(){
       NODEqueue[N];
       int top;
       inti, j,k;
       top = 0;
        queue[top].ind = 初始点;
        queue[top++].level = 0;
       标记初始点;
       for(i = 0;i <top; i++){//队列中还有未处理点
   j = 队列中下一个处理点;
   for(j的所有邻接点){
          if(该邻接点为被标记){
   queue[top].ind = 邻接点;
                             queue[top++].level = queue[i].level + 1;
                              if(该邻接点== 终点)
                                     returnqueue[i].level + 1;
   标记该邻接点;
                       }
                }
       }
      return -1;
}


其中

typedefstruct{
        intind;
        int level;
} NODE;


DFS– 深度优先搜索

DFS 在访问图中某一起始顶点A后,由A出发,访问它的任一邻接顶点B;再从B出发,访问与B邻接但还没有访问过的顶点E;然后再从E出发,进行类似的访问,… 如此进行下去,直至到达所有的邻接顶点都被访问过的顶点G为止。接着,  退回一步,  退到前一次刚访问过的顶点,看是否还有其它没有被访问的邻接顶点。如果有,则访问此顶点,之后再从此顶点出发,进行与前述类似的访问;如果没有,就再退回一步进行搜索。重复上述过程,直到连通图中所有顶点都被访问过为止。

BFS DFS 的比较

可以看到,广度优先搜索是按层次来搜索的,根据第一层遍历出第二层,当第二层全部被访问完之后,再处理第二层,由第二层访问到第三层,依次类推,直到处理完最后一层。

深度优先搜索是运用堆栈,从第一层的一个点,递归到第二层的一个点,再递归到第三层,到最后一层后,在回溯到上一层,然后从上一层递归到它的下一层的另一个点,直到它的所有点都被访问完,再回溯到上一层,依此类推,直到回溯到起点,这时所有的点都被访问完,最后形成一棵树的形状。

我们可以把BFS 形象地当作是水波的扩散,而DFS

则是顺藤摸瓜.

DFS 代码分析

void DFS( Point P ){
每次递归到一个点,则检查是否存在与它相邻,而且未被访问的点,有则递归访问这个点,无则返回上一层。
       inti;
       for(所有P的邻接点K){//每次递归到一个点,则检查是否存在与它相邻,而且未被访问的点,有则递归访问这个点,无则返回上一层。
                if(K未被访问){
                         标记K;
                         DFS(K);
                }
       }
}


DFS& BFS

这两种搜索方法除了可以用来遍历图以外,也常用来搜索各种状态,最常见的就是用来搜索最优值,或者搜索某种状态是否存在等等。

深度优先搜索的做法是:每递归到一层,则改变这一层的状态,之后递归到下一层,下一层同样改变它那一层的状态,递归到再下一层,当递归到最后一层时,每层的状态会形成一个最终的状态,我们需要将这个状态与得到的其他状态作比较,保留其中较优的一个。

当某一层的所有状态都被改变过一次后,回溯到上一层。每层都作类似的操作,最后所有的状态都会被搜索到,我们最后保留的较优值就是要求的最优值。


DFS代码分析

void DFS( int depth ){
   inti;
   if (depth > n){
       if (搜索到结果)  比较并记录;
       return;
   }
   else{
       for(所有状态)
            if (符合递归条件){
                    标记状态;
                    dfs(depth + 1 );
                    回溯;
            }
   }
}

可以看到,这样的搜索,时间复杂度是(a^n)的,a为每次的状态数,n为总的递归层数。

这个复杂度属于指数复杂度,当n比较大时,很荣易超时,所以,一般在n比较小的时候有深搜。

而且很多情况下需要剪枝。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值