你必须会的DFS的递归实现与堆栈实现
文章目录
- 一. 算法原理
- 1.堆栈式实现方法
- 2.递归式实现方法
- 二.具体实现
- 1.实例
- 2.结果
- 三.如何输出所有的路径?
一. 算法原理
相比于BFS利用队列实现中心扩散式搜索
DFS就是利用堆栈的思想(先进后出),利用回溯算法,或者使用dfs递归,直观上看是一条路走到黑,如果找到南墙,便回到上个路口,继续一条路走到黑…如此往复,直到到达目标,所以称之为深度优先搜索。
1.堆栈式实现方法
- 首先将根节点压入堆栈中。
- 从堆栈中pop一个节点,并检验它是否为目标。
- 如果找到目标,则结束搜索并回传结果。
- 否则将它所有尚未检验过的直接子节点加入堆栈中。
- 若堆栈为空,表示整张图都检查过了——亦即图中没有所搜索的目标。结束搜索并回传“找不到目标”。
- 重复步骤2。
伪代码
stack.push(root)
while(!stack.isEmpty())node = stack.pop()for each neighbor node的相邻节点if neighbor未被访问stack.push(neightbor)//记录路径stack.parent = node//其余操作...todo...
2.递归式实现方法
- 给定根节点
- 遍历根节点所有未被访问的相邻节点
- 如果找到目标,则结束搜索并传回结果
- 否则将该相邻节点设置为新的根节点,重复步骤2
- 若没有未被访问的相邻节点,则结束本分支的搜索并返回
- 所有分支都遍历完毕,结束搜索并回传“找不到目标”。
伪代码:
DFS()dfsVisit(root)dfsVisit(node)for each neighbor node的相邻节点if neighbor没有访问过//记录路径neighbor.parent = root//其他操作todo..dfs(neighbor)
二.具体实现
选用常见的递归实现
package com.example.DFS;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class DFS {// <1, [2, 3]>表示节点1的父节点是节点2,到源点距离为3private Map<Integer, int[]> disTo;/*** @param edges 一个节点到其他节点的距离* [[0, 1, 1], [1, 2, 2]] 表示点0到点1的距离为1,点1到点2的距离为2* @param n 所有节点个数 1<= n <= 1000* @param k 源节点 1< k <n*/public Map<Integer, int[]> DFS(int[][] edges, int n, int k){//通过edges数组生成有向图//<0, <{1,2}, {2,3}>>表示节点0有1,2两个相邻节点,距离分别为2, 3Map<Integer, List<int[]>> graph = new HashMap<>();for(int[] edge:edges){if(!graph.containsKey(edge[0]))graph.put(edge[0], new ArrayList<int[]>());graph.get(edge[0]).add(new int[]{edge[1], edge[2]});}//初始化disTodisTo = new HashMap<>();for(int i=0; i<n; i++){if(i==k)disTo.put(i, new int[]{k, 0});else disTo.put(i, new int[]{-1, Integer.MAX_VALUE});}dfsVisit(graph, k);return disTo;}/*** dfs* @param graph* @param k*/private void dfsVisit(Map<Integer, List<int[]>> graph, int k){if(graph.containsKey(k))for(int[] edge:graph.get(k)){int[] temp = disTo.get(edge[0]);//保证该节点未被访问if(temp[0] == -1 && temp[1] == Integer.MAX_VALUE) {//setParent 记录路径temp[0] = k;//setDisTo 记录距离temp[1] = disTo.get(k)[1] + edge[1];//递归实现dfsVisit(graph, edge[0]);}}}/*** 输出结果* @param disTo* @param end*/public void printPath(Map<Integer, int[]> disTo,int pathTo){int distance = disTo.get(pathTo)[1];List<Integer> path = new ArrayList<>();int temp = pathTo;path.add(temp);while (temp!=0 && temp!=-1){temp = disTo.get(temp)[0];path.add(temp);}System.out.print("从初始节点到节点"+end+"的距离为"+distance+"\n"+"路径为:\n"+path.get(0));for(int i=1;i<path.size();i++){System.out.print("<--"+path.get(i));}}
}
1.实例
测试输入
输入:
edges: | n: | k: | pathTo: |
---|---|---|---|
{{0, 1, 15},{0, 3, 5}, | 6 | 0 | 4 |
{1, 5, 6}, {3, 5, 20}, | |||
{1, 2, 15}, {3, 2, 30}, | |||
{2, 4, 10}, {5, 4, 9}}; |
预计输出:距离:30 路径:0–>1–>5–>4
环境:windows10,java11
2.结果
试着输出到节点5的路径和距离
三.如何输出所有的路径?
在一个图没有环的情况下,或者先去环后,允许一个节点可以由多个不同的父节点向下遍历到,这样可以找到图中真正的所有路径
你可能还敢兴趣的图论算法(均附Java实现代码):
算法实验–主函数只有五行的Floyed的算法以及最短路径输出
你必须会的–Dijkstra算法–单源最短路径问题
你了解欧拉回路吗?
你必须会的启发式搜索算法–A*算法
你必须会的DFS的递归实现与堆栈实现相关推荐
- C语言过河问题主函数,c,c++_C语言踩石头过河问题,用DFS搜索递归了17万次但是没报错,请问是什么原因?,c,c++,算法 - phpStudy...
C语言踩石头过河问题,用DFS搜索递归了17万次但是没报错,请问是什么原因? 这是原题目,后面附上我的代码,刚刚接触DFS,不是很熟练,求教育--谢谢!!!TUT 这是题目,我大概概括一下 用'※'和 ...
- 汉诺塔的非递归实现(借助堆栈模拟递归)
汉诺塔的非递归实现 借助堆栈以非递归(循环)方式求解汉诺塔的问题(n,a,b,c).即将n个盘子从起始柱(标记为"a")通过借助柱(标记为"b")移动到目标杜( ...
- Javascript中递归造成的堆栈溢出及解决方案
Javascript中递归造成的堆栈溢出及解决方案 参考文章: (1)Javascript中递归造成的堆栈溢出及解决方案 (2)https://www.cnblogs.com/cuew1987/p/4 ...
- 图的dfs非递归_如何理解恶心的递归
力扣leetcode-cn.com 递归恶心主要恶心在无论是做题还是解析都比较抽象,这里记录一下递归小白的理解过程: # Definition for a binary tree node. 以上图 ...
- POJ - 2083 Fractal(dfs,递归画图)
题目链接:点击查看 题目大意:给出一个n,要求递归画图 题目分析:重点就是设计递归啦,也没什么好说的,因为题目保证了n小于等于7,然后矩阵的大小为3^(n-1)*3^(n-1)所以矩阵最大不超过729 ...
- DFS迷宫递归所有路径 新手入门
这篇文章写给自己以后复习和个个入门朋友:提示同学们一定耐心看完解释 哪怕看得很难受,我是新手我懂大家的心烦.看完后慢慢体会代码 我们假设迷宫为如下状况: {0,0,1,0} ...
- 【PAT - 甲级1004】Counting Leaves (30分) (dfs,递归)
题干: A family hierarchy is usually presented by a pedigree tree. Your job is to count those family me ...
- 迷宫探索DFS(递归记录来回路径)
Problem Description 有一个地下迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关:请问如何从某个起点开始在迷宫中点亮所有的灯并回到起点? Input ...
- 水管工游戏:dfs(递归)
添柴网这题好想不能评测,所以不确保代码的正确性 题目描述: 这小节有点难,看不太懂可以跳过哦. 最近小哼又迷上一个叫做水管工的游戏.游戏的大致规则是这样的.一块矩形土地被分为N * M的单位正方形,现 ...
最新文章
- 物体的三维识别与6D位姿估计:PPF系列论文介绍(一)
- vs2008编译中文变量名的lua解释器环境
- 运算符重载 返回类型说明符后加_Java学习:运算符的使用与注意事项
- Poj(1459),最大流,EK算法
- mysql下拉框记忆,Mysql alter语句记忆分析
- Hibernate的数据过滤查询
- python任务调度平台 界面_分布式任务调度平台XXL-JOB
- CF980D Perfect Groups
- P5299-[PKUWC2018]Slay the Spire【dp】
- 数据结构与算法————九九乘法表
- (85)FPGA显示激励(monitor)
- Android开发学习之ImageView手势拖拽、缩放、旋转
- startlogging中设置setstdout=false来禁用这个功能。_无线路由器的安全功能,你知道多少?...
- 多标签分类任务大赛50万奖金等你来
- 6. ubuntu 下 mysql 数据库迁移
- 【POJ 3279】【开关问题】Fliptile【暑期 No.5】
- 虚拟机在教学实验中的应用
- 系分 02 软件工程
- ARMv8-A编程指导之Caches(1)
- PMP备考之路 - 汪博士第六章(项目进度管理)
热门文章
- TCP/IP协议族(一) HTTP简介、请求方法与响应状态码
- 用vs2008打开vs2012项目
- Java字符串的子串
- DeepEarth中的拖放行为(DragBehavior)
- Oracle常用系统表
- 神经网络与机器学习 笔记—改善反向传播的性能试探法
- 【数字信号处理】基本序列傅里叶变换总结 ( 单位脉冲序列 δ(n) | {1} 序列 | e^jωn 序列 | cosωn 序列 | sinωn 序列 | a^nu(n) | 矩形窗函数 ) ★★★
- 【C 语言】二级指针案例 ( 字符串切割 | 返回 自定义二级指针 作为结果 )
- 【错误记录】Java 中 ArrayList 排序 ( 使用 Comparator 接口时注意 compare 返回值是 -1 和 +1 )
- 【C 语言】文件操作 ( 读文本文件 | 文本加密解密 | fgets 函数 | fputs 函数 )