程序员面试经典--有向图路径验证
来源:互联网 发布:网络交换机图片 编辑:程序博客网 时间:2024/05/13 18:15
4.2问题:
给定有向图,设计一个算法,找出两个节点之间是否存在一条路径。
思考:
只需通过图的遍历,比如深度优先搜索或广度优先搜索等,就能解决这个问题。我们从两个节点的其中一个出发,在遍历过程中,检查是否找到另一个结点。在这个算法中,访问过的结点都应标记为“已访问”,以免重复访问结点。
关于邻接表与图的基本实现与操作:
import java.util.*;/** * 邻接表实现的图 * @author ctk * */class ListGraph { List<GraphNode> gNodes ;//头结点链表 private int vertex ;//图的结点数目 private int edges ;//边数目 public ListGraph(int vertex){//构造方法 this.vertex = vertex ; gNodes = new ArrayList<>(vertex);//给头结点链表分配内存空间 for(int i=0;i<vertex;i++) { GraphNode gnode = new GraphNode(); gnode.setNodeIndex(i); gnode.setNext(null); gNodes.add(gnode); } } public List getNode(){//返回头结点链表return gNodes;} public void addEdge(int i,int j,int weight){//添加边 if(i >= vertex || j >= vertex || i < 0 || j < 0) { System.out.println("输入的i和j超过范围"); return; } GraphNode gnode = gNodes.get(i); boolean isAlter = false; while(gnode.getNext() != null) { if(gnode.getNodeIndex() == j) { gnode.setData(weight); isAlter = true; break; } gnode = gnode.getNext(); } if(i == j){ gnode.setData(weight); isAlter = true; } if(!isAlter){ GraphNode edgeNode = new GraphNode(); edgeNode.setData(weight); edgeNode.setNodeIndex(j); edgeNode.setNext(null); gnode.setNext(edgeNode); } } public int[][] getMartix(){//生成邻接矩阵,图以邻接矩阵的形式返回 int[][] martix = new int[vertex][vertex]; GraphNode temp = null; for(int i=0;i<gNodes.size();i++){ temp = gNodes.get(i); while(temp != null){ martix[i][temp.getNodeIndex()] = temp.getData(); temp = temp.getNext(); } } return martix; } public int getEdge(int i,int j){ //获得某边,获取某个边的权重 int weight = 0; if(i >= vertex || j >= vertex || i < 0 || j < 0) { System.out.println("输入的i和j超过范围"); return weight; } GraphNode temp = gNodes.get(i); while(temp != null){ if(temp.getNodeIndex() == j){ weight = temp.getData(); break; } temp = temp.getNext(); } return weight; } public int getVertex() {//获取全图的顶点数 return vertex; } public int getEdges() {//返回全图的边数 return edges; } /* public static void main(String[] args) { ListGraph graph = new ListGraph(5); graph.addEdge(0, 1, 2); graph.addEdge(0, 2, 3); graph.addEdge(1, 1, 4); graph.addEdge(2, 3, 6); int[][] martix = graph.getMartix(); for(int i =0;i<martix.length;i++){ for(int j=0;j<martix[i].length;j++) System.out.print(martix[i][j]+" "); System.out.println(); } System.out.println("获取边<1,1> :"+graph.getEdge(1, 1)); } */}class GraphNode{//节点类 private int nodeIndex;//结点标号 private int data;//结点数据State state=State.Unvisited;//所有顶点状态都初始化为 未被访问的状态。 private GraphNode next;//结点指针 public int getNodeIndex() {//返回顶点标号 return nodeIndex; } public void setNodeIndex(int nodeIndex) {//设置顶点标号 this.nodeIndex = nodeIndex; } public int getData() {//返回结点数据 return data; } public void setData(int data) {//设置结点数据 this.data = data; } public GraphNode getNext() {//获取该结点指向的下一个结点 return next; } public void setNext(GraphNode next) {//设置该结点指向的下一个结点 this.next = next; }}enum State{//枚举类,标识节点被访问状态。Unvisited,Visited,Visiting;}
路径搜索函数:
public static boolean search(ListGraph g,GraphNode start,GraphNode end){//广搜 迭代实现 DFS//当作队列使用for(GraphNode v:g.gNodes){ //每次搜索前先将首结点链表里的顶点状态都设置为 Unvisited .v.state=State.Unvisited;}LinkedList<GraphNode> q = new LinkedList<GraphNode>();//q队列用于记录正在访问这一层和上一层的顶点。start.state=State.Visiting;q.add(start);GraphNode u;while(!q.isEmpty()){u = q.removeFirst();//也即 dequeue()//System.out.println("aa "+ u.getNodeIndex());for(GraphNode v=u.getNext();v!=null;v=v.getNext()){//遍历u顶点的邻接顶点System.out.println("bb "+ v.getNodeIndex());if(v.state==State.Unvisited){//判断是否被访问过if(v.getNodeIndex()==end.getNodeIndex()){//判断是否遍历到目标顶点return true;}else{q.add(g.gNodes.get(v.getNodeIndex()));//将该顶点入队列,这里需要注意入栈的是首结点链表里的顶点。//System.out.println("入队成功"+v.getNodeIndex());}}}u.state=State.Visited;}return false;}public static void BFS_path(ListGraph g,int i,int j){//广度优先搜索路径if(search(g,g.gNodes.get(i),g.gNodes.get(j))){System.out.println("存在路径: "+i+" ->...-> "+j);}else{System.out.println("不存在路径: "+i+" ->...-> "+j);}}
主函数内容:
public static void main(String args[]){ListGraph graph = new ListGraph(5); graph.addEdge(0, 1, 1); graph.addEdge(0, 2, 1); graph.addEdge(1, 4, 1); graph.addEdge(2, 3, 1); int[][] martix = graph.getMartix();System.out.println("该图的邻接矩阵表示如下:"); for(int i =0;i<martix.length;i++){ for(int j=0;j<martix[i].length;j++) System.out.print(martix[i][j]+" "); System.out.println(); } System.out.println("边<0,1>的权重为:"+graph.getEdge(0, 1));System.out.println();BFS_path(graph,0,1);BFS_path(graph,0,2);BFS_path(graph,0,3);BFS_path(graph,0,4);BFS_path(graph,1,2);BFS_path(graph,1,3);BFS_path(graph,1,4);BFS_path(graph,2,3);BFS_path(graph,2,4);BFS_path(graph,3,4);}
如需自己跑跑这个代码,还需要稍微组织一下。
测试结果如下:
0 0
- 程序员面试经典--有向图路径验证
- 《程序员面试金典》有向路径检查
- 程序员面试金典题解 有向路径检查
- 程序员面试金典-4.2有向路径检查
- 程序员面试金典——有向路径检查(图)
- 有向图 路径
- 程序员面试金典:二叉树平衡检查、有向路径检查
- 程序员面试金典: 9.4树与图 4.2给定有向图,设计一个算法,找出两个节点之间是否存在一条路径。
- 《程序员面试金典》--图中有向路径的检查
- 最短路径(有向图)
- 有向图的最短路径
- 有向图中的最长路径
- 有向图的关键路径
- 有向图中的最短路径
- 检查图中的有向路径
- 有向图路径存在判断
- 有向图最短路径
- 有向路径检查
- hive中UDF开发:解析json对象和解析json数组对象
- bootstrap-fileinput上传失败反馈信息
- 当原图片加载失败时,如何让图片加载上我们默认给的图片
- Android:Vector Drawable 使用
- i.MX 6UL应用处理器:高能效、超安全,为中国市场量身定制
- 程序员面试经典--有向图路径验证
- google官方的下拉刷新+自定义上拉加载更多
- Java面试准备十六:数据库——MySQL性能优化
- 大牛给计算机专业学生的 7 个建议
- 【腾讯云的1001种玩法】Nginx网站使用CDN之后禁止用户真实IP访问的方法
- VScode常用快捷键
- Nginx+Keepalived
- linux下安装php扩展
- spring 学习 错误记录