public void GenShortestPath(int startNo, int endNo) { GenNodes(); GenEdgeTable(startNo); if (EdgeNode.SearchEdgeNodeNo(edgeNodes, endNo) < 0) { Console.WriteLine(0); return; } Dijkstra(startNo, endNo); PrintShortestPath(startNo, endNo); }
private void PrintShortestPath(int startNo, int endNo) { int endEdgeNodeNo = EdgeNode.SearchEdgeNodeNo(edgeNodes, endNo); // 未寻到路 if (preNodeNos[endEdgeNodeNo] == NULL_NODE) { Console.WriteLine(0); return; } int distance = distances[endEdgeNodeNo]; // 逆序寻找前趋节点 var path = new List <int>(); while (endEdgeNodeNo != INIT_NODE) { path.Insert(0, endEdgeNodeNo); endEdgeNodeNo = preNodeNos[endEdgeNodeNo]; } // 修改矩阵 foreach (var j in path) { int x = edgeNodes[j].node.x; int y = edgeNodes[j].node.y; martrix[y][x] = 2; } // 打印 Console.WriteLine(distance); for (int i = 0; i < size; i++) { Console.WriteLine(string.Join(" ", martrix[i])); } }
// 从起点开始用广度优先遍历方式建立相邻节点表,可覆盖从起点开始所有可达的节点,组成一张连接拓扑图 private void GenEdgeTable(int startNo) { edgeNodes = new List <EdgeNode>(); var totalNos = new List <int>(); var newNos = new List <int>(); newNos.Add(startNo); while (newNos.Count > 0) { var newNos2 = new List <int>(); foreach (var no in newNos) { var node = nodes[no]; if (node.value == 1) { continue; } if (totalNos.Contains(node.no)) { continue; } totalNos.Add(no); var edgeNode = new EdgeNode(node, nodes); edgeNodes.Add(edgeNode); foreach (var newNo in edgeNode.neighborNos) { if (!totalNos.Contains(newNo) && !newNos.Contains(newNo) && !newNos2.Contains(newNo)) { newNos2.Add(newNo); } } } newNos = newNos2; } }
// Dijkstra最短路径算法 private void Dijkstra(int startNo, int endNo) { var s = new List <int>(); //已找到最短路径的端点 //var u = new List<int>(); //未找到最短路径的端点 for (int i = 0; i < MAX_SIZE * MAX_SIZE; i++) { distances[i] = MAX_DISTANCE; // 初始化为最长距离 preNodeNos[i] = NULL_NODE; // 初始化为无前趋节点 } //初始化将第一个节点加入s,其余加入待定集合u int selectEdgeNodeNo = EdgeNode.SearchEdgeNodeNo(edgeNodes, startNo); s.Add(selectEdgeNodeNo); distances[selectEdgeNodeNo] = 0; //修改距离 preNodeNos[selectEdgeNodeNo] = INIT_NODE; // 修改前趋节点 if (edgeNodes.Count <= 1) { return; } // 当待定集合U里节点不为空时 while (s.Count < edgeNodes.Count) { // 根据选定的新加入节点更新待定集合u中节点的距离和前趋节点 foreach (var nodeNo in edgeNodes[selectEdgeNodeNo].neighborNos) { int edgeNodeNo = EdgeNode.SearchEdgeNodeNo(edgeNodes, nodeNo); if (s.Contains(edgeNodeNo)) { continue; } // 如果经过新加入节点的新路比老路距离短 if (distances[edgeNodeNo] > distances[selectEdgeNodeNo] + 1) { distances[edgeNodeNo] = distances[selectEdgeNodeNo] + 1; //修改距离 preNodeNos[edgeNodeNo] = selectEdgeNodeNo; //修改前趋节点 } } // 选定新的S节点,挑选U里路径最短的 int min = MAX_DISTANCE; int newNo = NULL_NODE; for (int i = 0; i < edgeNodes.Count; i++) { if (s.Contains(i)) { continue; } if (distances[i] < min) { min = distances[i]; newNo = i; } } selectEdgeNodeNo = newNo; s.Add(selectEdgeNodeNo); // 如果选定节点是结束点,则提前结束算法 if (edgeNodes[selectEdgeNodeNo].node.no == endNo) { return; } } }