我目前正在做一个学校作业,希望我们使用图形(无向)对公交路线图进行建模,其中边表示标有设置为公交路线字母的标签的道路(一条道路可能有公交车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的边缘进行比较,以查看总线路由是否相同(如果不同)同样,然后检查是否还有足够的公交车更换。
到目前为止,我的运行确实没有错误,但是打印出的解决方案已经是一个空列表,即使不是。
我们刚刚在图形上开始了本主题,并且仅用于分配作业。
编辑:示例图和解决方案:
如果允许更改1条总线,则该地图路线的路径对于节点为0、1、5、6、10。