java实现DFS求路径是否有解问题

来源:互联网 发布:免费的儿童教育软件 编辑:程序博客网 时间:2024/06/12 01:33

今天回顾了DFS——Depth First Search——深度优先遍历,这个算法主要有两个用途:一是用于对于未知解的探索,一个典型的例子是走迷宫,也就是我们要列出所有的可能性来穷举,如果找到一条可行之路那么说明我们要解决的问题有戏,如果到最后也没有找到一条可行之路,那么说明我们的问题没有解。二是作为拓扑排序的基石,这一点我们以后再讲。

那么如何来实现DFS算法呢? 我们需要的原料有:结点、边、结点数、以及一个很重要的标记数组——来标记某个结点是否已经被访问过了,这可以避免我们在图中来来回回鬼打墙。

public class DFS {private char[] vertices;private int verticeNum;private boolean[] isVisited;private int[][] edges;

第二步我们通过这个类的一个有参构造函数初始化一下这些原始材料。

public DFS(int n) {vertices = new char[n];verticeNum = n;isVisited = new boolean[n];for(int i = 0; i<n;i++){isVisited[i] = false;}edges = new int[n][n];for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {edges[i][j] = 0;}}}

第三步,我们实现加边、加点、访问结点的函数封装,为后续代码的简洁直观打基础

public void addEdge(int i,int j){  //避免加入起点和终点相同的边,其实也就是一个点了……if(i==j)return;edges[i][j] = 1;edges[j][i] = 1;}public void setVertices(char[] vertices){this.vertices = vertices;}public void visit(int i){System.out.print(vertices[i] + " ");}



第四步,是一个很重要很核心的递归函数,基本思想就是,深度访问到某一个结点时,访问它并将之标记为已访问。然后在所有的结点中,找这个结点的未访问过的邻结点(也就是和这个结点 由边连接的结点),对邻接点进行深度上的访问。

public void traverse(int i){isVisited[i] = true;visit(i);for(int j = 0; j<verticeNum;j++){if(edges[i][j] ==1 && isVisited[j] ==false){traverse(j);}}}
第五步,在DFS算法的主方法中对图中的每一个结点进行遍历。 我们可以看到,DFSTraverse 函数对每一个结点调用递归函数traverse,traverse函数中有有用到visit函数的地方,我觉得这种封装很棒。

public void DFSTraverse(){for(int i = 0; i< verticeNum;i++){if(!isVisited[i] )traverse(i);}}
最后,在main函数中实例化,用例子来试一下。

public static void main(String[] args) {DFS g = new DFS(9);char[] vertices = {'A','B','C','D','E','F','G','H','I'};g.setVertices(vertices);        g.addEdge(0, 1);        g.addEdge(0, 5);        g.addEdge(1, 0);        g.addEdge(1, 2);        g.addEdge(1, 6);        g.addEdge(1, 8);        g.addEdge(2, 1);        g.addEdge(2, 3);        g.addEdge(2, 8);        g.addEdge(3, 2);        g.addEdge(3, 4);        g.addEdge(3, 6);        g.addEdge(3, 7);        g.addEdge(3, 8);        g.addEdge(4, 3);        g.addEdge(4, 5);        g.addEdge(4, 7);        g.addEdge(5, 0);        g.addEdge(5, 4);        g.addEdge(5, 6);        g.addEdge(6, 1);        g.addEdge(6, 3);        g.addEdge(6, 5);        g.addEdge(6, 7);        g.addEdge(7, 3);        g.addEdge(7, 4);        g.addEdge(7, 6);        g.addEdge(8, 1);        g.addEdge(8, 2);        g.addEdge(8, 3);       System.out.print("深度优先遍历(递归):");       g.DFSTraverse();}
我们可以得到结果:深度优先遍历(非递归):A B C D E F G H I 

PS:附赠非递归DFS实现。

其基本思想就是,用到栈,利用栈后进先出的结构特点,每弹出一个结点,就将此结点的未访问过的邻结点放入栈,这样下次从栈中取出的就是往深处走的邻结点,当走到头的时候再取出来的结点就是返回遇到的第一个分岔路口了。

public void DFSNoRecurion(){Stack<Integer> stack = new Stack<Integer>();for(int i = 0; i< verticeNum;i++){if(!isVisited[i] ){stack.push(i);do{int cur = stack.pop();if(!isVisited[cur]){visit(cur);isVisited[cur] = true;for(int j =0;j < verticeNum;j++){if(edges[cur][j] ==1 && !isVisited[j]){stack.push(j);break;}}}}while(!stack.isEmpty());}}}








1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 集成墙面挂照片怎么办 苹果电脑网页游戏打不开怎么办 苹果6plus发热怎么办 玩手游手机太卡怎么办 苹果七发烫厉害怎么办 苹果手机延迟高怎么办 王者荣耀总是卡怎么办 王者荣耀卡屏怎么办 王者荣耀网络延迟怎么办 荣耀8手机卡了怎么办 荣耀v10有点卡怎么办 荣耀10有点卡怎么办 8g内存吃鸡会崩怎么办 玩看门狗很卡怎么办 拼多多人数不够怎么办 玩cf想吐怎么办 玩手机头晕恶心怎么办 玩手机头疼恶心怎么办 看手机想吐怎么办 英雄联盟取名后怎么办 王者荣耀改名重复怎么办 刺激战场改名重复怎么办 省钱快报忘记密码怎么办 手机直播网速卡怎么办 触手tv直播黑屏怎么办 酷狗id密码忘记怎么办 打游戏网络不稳定怎么办 电脑打字法没了怎么办 家庭版密钥专业版系统怎么办 win7应用程序不能启动怎么办 win7用户密码忘记了怎么办 win7用户密码忘了怎么办 windows开不了机怎么办 网卡被卸载了怎么办 win7注销黑屏了怎么办 w7密码忘了怎么办 笔记本电脑键盘进水了怎么办 笔记本键盘进水了怎么办 笔记本进水键盘失灵怎么办 win7进不了系统怎么办 电脑显示屏两边黑屏怎么办