深度优先搜索(DFS)
来源:互联网 发布:bp神经网络算法 matlab 编辑:程序博客网 时间:2024/06/06 09:55
一、概述
深度优先搜索英文全称为(Depth-First search),简称DFS。为图的一种遍历方式,所采用的策略可概况为优先选取最后一个被访问到的顶点的邻居。于是,以顶点s为基点的DFS搜索,将首先访问顶点s;再从s所有尚未访问到的邻居中任取其一,并以之为基点,递归地执行DFS搜索。故各顶点被访问到的次序,类似于树的先序遍历,当访问到该顶点没有了邻居顶点,于是就回溯访问,而各顶点被访问完毕的次序,则类似于树的后序遍历。
二、实现
从图中选取一个顶点,作为第一次DFS 的起始顶点,从该顶点中的邻居顶点中任选其一,作为基点,再从该顶点中的邻居顶点中任选其一,依次递归,直到到达最后一个没有邻居顶点的顶点。然后返回上一个顶点,选取它另外一个邻居顶点,然后以此类推。直到所有图中所有顶点被访问完毕。
下图来表示遍历过程
DFS树中v是否为u的祖先,若是(v,u)为前向边(forward edge),否则为后向边(backward edge), 若二者来自相互独立的两个分支,则为跨边(cross edge)
图(u)表示选取D为起始顶点
三、代码
下列代码是Java编写的,用一个整型数值来代表一个顶点
创建图的操作接口
package cn.adt.dfs.graph;import java.util.Set;/** * Created by YangT on 2017-8-11. * 图的顶点用整形来表示 */public interface Graph { boolean addVertex(Integer v); Double addEdge(Integer from,Integer to); boolean addEdge(Integer from,Integer to,Double weigth); boolean removeVertex(Integer v); boolean removeEdge(Integer from,Integer to); Set<Integer> getVertices(); Set<Integer> getNeighbors(Integer v); int size();}
一个有向图实例
package cn.adt.dfs.graph;import java.util.HashMap;import java.util.HashSet;import java.util.Map;import java.util.Set;import cn.adt.dfs.graph.Graph;/** * Created by YangT on 2017-8-11. * 有向图 */public class DirectedGraph implements Graph { private Map<Integer,Set<Integer>> vertexMap = new HashMap<>(); /** * map的键存放顶点,值存放与该顶点相连的顶点 */ @Override public boolean addVertex(Integer v) { vertexMap.put(v, new HashSet<Integer>()); return true; } @Override public Double addEdge(Integer from, Integer to) { if(!vertexMap.containsKey(from)) return -1d; if(!vertexMap.containsKey(to)) return -1d; vertexMap.get(from).add(to); return 0d; } @Override public boolean addEdge(Integer from, Integer to, Double weigth) { //当前不支持带权图 return false; } @Override public boolean removeVertex(Integer v) { if(!vertexMap.containsKey(v)) return false; vertexMap.remove(v); return true; } @Override public boolean removeEdge(Integer from, Integer to) { if(!vertexMap.containsKey(from)) return false; if(!vertexMap.containsKey(to)) return false; vertexMap.get(from).remove(to); return true; } @Override public Set<Integer> getVertices() { return vertexMap.keySet(); } @Override public Set<Integer> getNeighbors(Integer v) { return vertexMap.get(v); } @Override public int size() { return vertexMap.size(); }}
DFS实现
package cn.graph.dfs;import java.util.HashMap;import java.util.HashSet;import java.util.LinkedList;import java.util.List;import java.util.Map;import java.util.Set;import java.util.Stack;import cn.adt.dfs.graph.Graph;/** * Created by YangT on 2017-8-11. * 图的顶点用整形来表示 */public class DFS { private Graph graph; //创建一个时间,来表示整个DFS时间,各顶点的状态 private Integer clock = 0; //创建各顶点入栈时间map,也就是被发现时间 private Map<Integer,Integer> ftimeMap = new HashMap<>(); //创建各顶点出栈时间map,也就是回溯该顶点时间 private Map<Integer,Integer> dtimeMap = new HashMap<>(); private List<Integer> path = new LinkedList<>(); private Set<Integer> visited = new HashSet<>(); private Stack<Integer> stack = new Stack<>(); public DFS(Graph graph){ this.graph = graph; } //搜索 public void search(Integer source){ if(source == null || !graph.getVertices().contains(source)) return; path.add(source); visited.add(source); stack.push(source); ftimeMap.put(source, ++clock); for(Integer neighbor : graph.getNeighbors(source)){ //判断该顶点是否已被访问 if(visited.contains(neighbor)) continue; search(neighbor); } Integer v = stack.pop(); dtimeMap.put(v, ++clock); } //显示顶点被发现和回溯完成的时间 public void showTime(){ Set<Integer> keys = ftimeMap.keySet(); for (Integer key : keys) { System.out.print("入栈时间 " + key + ":" + ftimeMap.get(key) + " "); } System.out.println(" "); Set<Integer> dkeys = dtimeMap.keySet(); for (Integer key : dkeys) { System.out.print("出栈时间 " + key + ":" + dtimeMap.get(key) + " "); } } //检查所有顶点是否都已访问到 public boolean check(){ if(graph.size() != visited.size()){ return false; } return true; } /** * 获取访问顺序 */ public List<Integer> getPath(Integer source){ if(source == null || !graph.getVertices().contains(source)) return null; search(source); /** * DFS从一个顶点开始,不可能访问到所有顶点,因此要另取一个顶点,做第二次DFS */ while(!check()){ for (Integer v : graph.getVertices()) { if(!visited.contains(v)){ search(v); } } } return path; }}
测试代码
package cn.test;import java.util.List;import cn.adt.dfs.graph.DirectedGraph;import cn.adt.dfs.graph.Graph;import cn.graph.dfs.DFS;/** * Created by YangT on 2017-8-11. * 图的顶点用整形来表示 */public class DFSTest { public static void main(String[] args) { /** * 创建一个有向图,顶点用整型数值来表示 */ Graph g = new DirectedGraph(); for (int i = 1; i < 8; i++) { g.addVertex(i); } g.addEdge(1, 2); g.addEdge(2, 3); g.addEdge(1, 3); g.addEdge(4, 1); g.addEdge(1, 6); g.addEdge(4, 5); g.addEdge(5, 6); g.addEdge(7, 1); g.addEdge(7, 3); g.addEdge(6, 7); DFS dfs = new DFS(g); /** * 从顶点1开始dfs * 输出各顶点的访问顺序 * 调用showTime方法,输出各顶点的被发现和回溯完成访问该顶点时间 */ List<Integer> paths = dfs.getPath(1); for (Integer v : paths) { System.out.print(v + " "); } System.out.println(" "); dfs.showTime(); }}
图的构造顶点由整型来代替。测试类创建的图仿照上面图片建立
代码不是很完善,希望能指正。如有错误,希望能指正,谢谢。
参考书籍:数据结构第三版 作者:邓俊辉
参考代码:
https://github.com/sherxon/AlgoDS/blob/master/src/algo/graph/DFS.java
阅读全文
0 0
- 深度优先搜索 DFS
- 深度优先搜索 DFS
- DFS 深度优先搜索
- DFS 深度优先搜索
- 深度优先搜索(DFS)
- 深度优先搜索(DFS)
- 深度优先搜索DFS
- DFS深度优先搜索
- 深度优先搜索(DFS)
- dfs深度优先搜索
- dfs 深度优先搜索
- 深度优先搜索(DFS)
- 深度优先搜索DFS
- DFS深度优先搜索
- 深度优先搜索(DFS)
- 深度优先搜索DFS
- 深度优先搜索(DFS)
- 深度优先搜索--DFS
- PHP Error 和 Logging 函数
- js打印div指定区域内容
- Something about cpu and memory hot plug on kvm
- DigitalOcean租VPS,配置过程
- 求最大子矩阵的和、求最大子数组的和
- 深度优先搜索(DFS)
- PHP 5 Date/Time 函数
- dp入门级--递推数塔
- QT+Gsoap访问cxf WebService
- PHP 5 Directory 函数
- iOS开发 --frame和bounds区别详解
- linux服务器上配置多个svn仓库
- 352A
- bzoj 1257: [CQOI2007]余数之和sum