深搜和广搜的原理及优缺点

深搜原理

深搜,顾名思义,是深入其中、直取结果的一种搜索方法。
  如果深搜是一个人,那么他的性格一定倔得像头牛!他从一点出发去旅游,只朝着一个方向走,除非路断了,他绝不改变方向!除非四个方向全都不通或遇到终点,他绝不后退一步!因此,他的姐姐广搜总是嘲笑他,说他是个一根筋、不撞南墙不回头的家伙。
  深搜很讨厌他姐姐的嘲笑,但又不想跟自己的亲姐姐闹矛盾,于是他决定给姐姐讲述自己旅途中的经历,来改善姐姐对他的看法。他成功了,而且只讲了一次。从那以后他姐姐不仅再没有嘲笑过他,而且连看他的眼神都充满了赞赏。他以为是自己路上的各种英勇征服了姐姐,但他不知道,其实另有原因……
  深搜是这样跟姐姐讲的:关于旅行呢,我并不把目的地的风光放在第一位,而是更注重于沿路的风景,所以我不会去追求最短路,而是把所有能通向终点的路都走一遍。可是我并不知道往哪走能到达目的地,于是我只能每到一个地方,就向当地的人请教各个方向的道路情况。为了避免重复向别人问同一个方向,我就给自己规定1 :先问北,如果有路,那就往北走,到达下一个地方的时候就在执行此规定,如果往北不通,我就再问西,其次是南、东,要是这四个方向都不通或者抵达了终点,那我回到上一个地方,继续探索其他没去过的方向。我还要求自己要记住2 那些帮过他的人,但是那些给我帮倒忙的、让我白费力气的人,要忘记3他们。有了这些规定之后,我就可以大胆的往前走了,既不用担心到不了不目的地,也不用担心重复走以前的路。哈哈哈……

深搜优缺点

  • 优点
    1、能找出所有解决方案
    2、优先搜索一棵子树,然后是另一棵,所以和广搜对比,有着内存需要相对较少的优点
  • 缺点
    1、要多次遍历,搜索所有可能路径,标识做了之后还要取消。
    2、在深度很大的情况下效率不高

深搜模板

void DFS() //N代表目前DFS的深度
{
	if(找到解) //进行相应的操作
	{return;
	}
	for(inti=0;i<4;i++) //枚举四个方向
	{
    	DFS(N+1); //进入下层递归
	}
}

广搜原理

广搜,顾名思义,是多管齐下、广撒网的一种搜索方法
  如果广搜是一个人,那么她一定很贪心,而且喜新厌旧!她从一点出发去旅游,先把与起点相邻的地方全部游览一遍,然后再把与她刚游览过的景点相邻的景点全都游览一边……一直这样,直至所有的景点都游览一遍。
  广搜属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。类似树的按层遍历,其过程为:首先访问初始点Vi,并将其标记为已访问过,接着访问Vi的所有未被访问过可到达的邻接点Vi1、Vi2…Vit,并均标记为已访问过,然后再按照Vi1、Vi2…Vit 的次序,访问每一个顶点的所有未被访问过的邻接点,并均标记为已访问过,依此类推,直到图中所有和初始点Vi有路径相通的顶点都被访问过为止。

广搜优缺点

  • 优点
    1、对于解决最短或最少问题特别有效,而且寻找深度小
    2、每个结点只访问一遍,结点总是以最短路径被访问,所以第二次路径确定不会比第一次短
  • 缺点
    1、内存耗费量大(需要开大量的数组单元用来存储状态)

广搜模板

void BFS() 
{ 	… …//初始化起点入队 
	while(!q.empty()) //判断队是否为空
	{	… …//获取队首元素
		if(...){… …}//判断是否是终点
		for(int i=0;i<4;i++)//四个方向
		{ 
			k.x=p.x+dir[i][0];
	    	k.y=p.y+dir[i][1];
			//向各个方向走一步
	     	if(judge())//判断能不能走
			{
		    	… …//各种处理 
    		    vis[k.x][k.y]=1; //标记 	
	        	q.push(k); //入队
			}
		}
	}
}

广搜打印路径:虽然它有多个后继结点,但前驱节点只有一个。所以可以逆向打印路径,即从终点出发找通向起点的路径


  1. 遍历四个方向 ↩︎

  2. 标记,标识已经走过的结点 ↩︎

  3. 取消标记 ↩︎

### 度优先索与广度优先索中的剪枝技术 #### 度优先索 (DFS) 中的剪枝技术 度优先索是一种沿着某个方向尽可能入探索节点的策略。然而,在实际应用中,可能会遇到大量的无意义路径或冗余计算。为了提高效率,可以通过剪枝来减少不必要的分支。 剪枝的核心思想是在索过程中提前判断某些子树是否可能包含目标解,如果不可能,则跳过这些子树的进一步扩展。例如,在解决约束满足问题时,可以利用当前状态下的约束条件排除那些无法满足最终解的状态[^1]。 以下是 DFS 的基本框架以及如何加入剪枝逻辑: ```python def dfs(node, visited): if is_invalid_state(node): # 判断当前状态是否无效(剪枝) return False if is_goal(node): # 如果找到目标则返回成功 return True visited.add(node) for neighbor in get_neighbors(node): if neighbor not in visited: if dfs(neighbor, visited): # 继续递归索邻居节点 return True return False ``` 在此代码片段中,`is_invalid_state()` 函数用于检测当前节点是否违反任何已知规则或约束条件。一旦发现不可行的情况即可立即停止对该分支的继续探索[^2]。 --- #### 广度优先索 (BFS) 中的剪枝技术 相比 DFS广度优先索按层展开索空间,通常适用于寻找最短路径等问题。尽管 BFS 能够提供最优解,但在大规模数据集上其内存消耗较高。因此引入剪枝同样有助于提升性能并降低资源占用。 对于 BFS 来说,常见的剪枝方法包括但不限于以下几种方式: - **启发式估计**:通过估算剩余距离或其他指标决定哪些候选项更值得保留; - **重复状态过滤**:避免多次访问相同的状态从而节省时间开销; - **边界限制设置**:只考虑一定范围内的可能性而忽略超出部分。 下面是一个带有简单剪枝机制的 BFS 示例程序: ```python from collections import deque def bfs(start_node): queue = deque([start_node]) visited = set() while queue: node = queue.popleft() if is_invalid_state(node): # 对于不符合条件的状态直接丢弃 continue if is_goal(node): # 找到解决方案即刻终止循环 break visited.add(node) neighbors = get_neighbors(node) for n in neighbors: if n not in visited and meets_pruning_criteria(n): # 只有符合条件的新邻接点才会被加入队列 queue.append(n) return None if not found_solution else solution_path ``` 这里 `meets_pruning_criteria()` 是一个自定义函数用来评估每一个候选者是否应该进入下一步处理阶段。 --- #### 总结比较两者差异及适用场景 | 特性 | 度优先索 | 广度优先索 | |--------------------|---------------------------------------|--------------------------------------| | 探索顺序 | 向下逐级入 | 层次化横向扫描 | | 存储需求 | 较低 | 高 | | 是否保证最佳答案 | 不一定 | 当存在单位权重边时可获得最小步数解答| 无论采用哪种基础算法形式,合理运用剪枝技巧都能够显著改善整体表现效果。值得注意的是具体实施方案需依据实际情况灵活调整以达到理想成效。 ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值