通过遍历图找到从头到尾的路径

时间:2018-11-28 21:21:12

标签: java graph-traversal undirected-graph

我目前正在做一个学校作业,希望我们使用图形(无向)对公交路线图进行建模,其中边表示标有设置为公交路线字母的标签的道路(一条道路可能有公交车a,但是另一条道路有可能有总线b),并且节点表示交叉点,死角或起点和终点。该地图采用矩形/正方形网格格式,因此节点可以具有的入射边缘的最大数量为4(这意味着相交处连接有4条道路)。

我已经实现了Node,Edge和Graph类,还设法将所有必需的边缘和节点添加到表示样本图的图形中。我现在必须编写一种使用迭代器的方法,该迭代器存储节点的所有入射边缘和一个整数值,该整数值表示允许进行多少次总线更改,然后遍历图形以查找一条从起始节点通向节点的路径。终端节点,而不使用比指定更多的总线更改。然后返回一个迭代器,该迭代器存储从头到尾在路径上传递的所有节点。

这是我到目前为止所用的方法(由于卡住而未完成):

public Iterator<GraphNode> trip() throws GraphException {
    GraphNode startNode = new GraphNode(startLoc); //Creates the starting node.
    listOfNodes.add(startNode); //Adds the starting node to the list of nodes that will be the solution.
    startNode.setMark(true); //Marks the starting node as true, meaning it has been visited.
    pathForEveryNode(graph.incidentEdges(startNode)); //Uses the custom method to find where to go next.
    return listOfNodes.iterator(); //Returns the iterator that stores the solution nodes.
}

private List<GraphNode> pathForEveryNode (Iterator<GraphEdge> incidentEdges) throws GraphException {
    //This checks if the current node has incident edges or not, if not, then null is returned.
    if (incidentEdges == null) {
        return null;
    } else {
        //If the current node does have incident nodes, check the first edge first.
        while (incidentEdges.hasNext()) {
            tryAgain:{ GraphEdge nextEdge = incidentEdges.next(); //The is the first edge to be checked.
                GraphNode endNode = nextEdge.secondEndpoint(); //This is the second end point of the current edge.
                /*
                 * Checks if the current edge and one of the edges connected to the second end point has
                 * the same bus route set. If not, then the number of changes needs to be checked, if it is,
                 * then add the second end point to the array list and move to the next set of incident edges.
                 */
                listOfNodes.add(endNode); //Adds the second end point to the array list.
                endNode.setMark(true); //Marks the second end point as true, meaning it has been visited.
                tryAgain2:{GraphEdge Snode = graph.incidentEdges(endNode).next();
                if (nextEdge.getBusLine() != Snode.getBusLine()) {
                    /*
                     * If the number of changes left is larger or equal to 1, it is decreased by 1. Otherwise,
                     * there is not enough changes left, so back track to the beginning and try the next edge available.
                     */
                    if (kNumOfChanges >= 1) {
                        kNumOfChanges--;
                        listOfNodes.add(Snode.secondEndpoint()); //Adds the second end point to the array list.
                        Snode.secondEndpoint().setMark(true); //Marks the second end point as true, meaning it has been visited.
                    } else if(kNumOfChanges == 0 && graph.incidentEdges(endNode).hasNext()){ //If the number of changes available or remaining is 0:
                        break tryAgain2; //Try a different edge connecting to the endNode.
                    } else if(kNumOfChanges == 0 && !graph.incidentEdges(endNode).hasNext()) {
                        listOfNodes.remove(endNode); //So the node is removed.
                        endNode.setMark(false); //Marks the second end point to false, meaning it has not been visited.
                        break tryAgain; //Try a different incident edge.
                    }
                } else {
                    listOfNodes.add(Snode.secondEndpoint()); //Adds the second end point to the array list.
                    Snode.secondEndpoint().setMark(true); //Marks the second end point as true, meaning it has been visited.
                }

                //If the second end point of the current node is the ending node, return the array list and end the program.
                if (Snode.secondEndpoint().getName() == endLoc) {
                    return listOfNodes;
                /*
                 * If it is not the ending node, check if all of its edges leads to an unmarked node (nodes that has not been visited).
                 * If there are no nodes that is unmarked (deadend), then this current node doesn't lead any where, so remove it from the 
                 * array list.
                 */
                } else if (pathForEveryNode(allPathPossibilitiesOneNode(graph.incidentEdges(Snode.secondEndpoint()))) == null) {
                    listOfNodes.remove(Snode.secondEndpoint()); //remove the current node from the array list.
                    Snode.secondEndpoint().setMark(false); //Marks the current node to be false, meaning it has not been visited.
                    listOfNodes.remove(endNode); //So the node is removed.
                    endNode.setMark(false); //Marks the second end point to false, meaning it has not been visited.
                    if (kNumOfChanges > 1) {
                        kNumOfChanges++;
                    }
                }

                //Checks if the array list contains the ending node, if it does, then return the array list. Otherwise, return null.
                boolean endLocInArray = false;
                for(int i = 0; i < listOfNodes.size(); i++) {
                    if (listOfNodes.get(i).getName() == endLoc) {
                        endLocInArray = true;
                        break;
                    }
                }

                if(endLocInArray == true) {
                    return listOfNodes;
                }
            }}
        }
    }
    return null;
}

和一个辅助方法,用于检查是否已经访问了第二个端点:

private Iterator<GraphEdge> allPathPossibilitiesOneNode(Iterator<GraphEdge> PossibilitiesIterator) {
    List<GraphEdge> allPathPossibilities = new ArrayList<GraphEdge>(); //Initializes the array list that will store the edges.
    //This loop goes through all the incident edges connecting to the current node.
    while (PossibilitiesIterator.hasNext()) {
        GraphEdge currentEdge = PossibilitiesIterator.next(); //The first incident edge.
        //This checks if the second end point (next intersection) is marked or not, if not, then add it to the array list.
        if (currentEdge.secondEndpoint().getMark() == false) {
            allPathPossibilities.add(currentEdge);
        }
    }
    //Return the iterator is the array list is not empty, otherwise return null.
    if (!allPathPossibilities.isEmpty()) {
        return allPathPossibilities.iterator();
    } else {
        return null;
    }
}

应该将连接到第一个节点的边缘的busLine标签(firstEndPoint)与连接到第一个边缘的secondEndPoint的边缘进行比较,以查看总线路由是否相同(如果不同)同样,然后检查是否还有足够的公交车更换。

到目前为止,我的运行确实没有错误,但是打印出的解决方案已经是一个空列表,即使不是。

我们刚刚在图形上开始了本主题,并且仅用于分配作业。

编辑:示例图和解决方案:

enter image description here

如果允许更改1条总线,则该地图路线的路径对于节点为0、1、5、6、10。

0 个答案:

没有答案