网格两点间路径坐标获取方法及代码报错求助
网格两点间路径坐标获取方法及代码报错求助
你好呀!看你说已经能判断矩阵两点间是否存在路径,但卡在获取具体路径坐标上,一开始考虑用链表来记录相邻节点,后来尝试用BFS的思路实现但遇到了编译错误,我来帮你分析下问题出在哪,再给你修正后的可行方案~
错误原因分析
第一个错误:
std::queue没有下标运算符
你提到的unvisitedNeighbours[0].pMain报错,是因为std::queue是队列容器,它只支持front()/back()访问队首/队尾元素,不支持用[]直接下标访问,应该是你调试时误写了这段代码,正常逻辑里队列不能这么用哦。第二个错误:
this指针使用不当
报错里的this->parent->parent...,this只能在类的非静态成员函数里使用,如果是在全局函数或者main里写了这段,肯定会报错,这应该也是调试时的误写,记得this的使用范围就好。
你的代码里还有这些隐藏问题
- 结构体
node的构造函数错误:你在构造函数里写了int index = _index;,这是定义了一个局部变量,根本没给成员变量index赋值,应该改成index = _index;或者用初始化列表更规范。 - 节点初始化语法错误:
node Node(node(make_pair(0, 0), make_pair(-1, -1), 0));这行是错误的,直接写node Node(make_pair(0, 0), make_pair(-1, -1), 0);就可以,不需要嵌套node()。 - 路径回溯逻辑错误:你用
index关联父节点的逻辑有问题,而且直接修改原数组标记已访问,会破坏输入数据,最好用单独的访问矩阵。 - 越界判断顺序错误:你先判断
arr[a][b] != -1再判断坐标是否合法,这样如果a或b越界,访问arr[a][b]会直接导致数组越界崩溃,应该先判断坐标是否在矩阵范围内。
修正后的完整代码
#include <vector> #include <iostream> #include <queue> #include <utility> using namespace std; const int row = 5; const int col = 5; struct node { pair<int, int> pMain; pair<int, int> parent; int index; // 用初始化列表正确初始化成员变量 node(pair<int, int> _p, pair<int, int> _parent, int _index) : pMain(_p), parent(_parent), index(_index) {} }; // 查找从(0,0)到(row-1, col-1)的路径,并输出路径坐标 bool findPath(int arr[row][col]) { // 四个方向:右、左、下、上 int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; // 单独的访问标记矩阵,避免修改原输入数组 bool visited[row][col] = {false}; queue<node> unvisitedNeighbours; vector<node> paths; // 初始化起点节点:坐标(0,0),父节点(-1,-1),索引0 node startNode(make_pair(0, 0), make_pair(-1, -1), 0); unvisitedNeighbours.emplace(startNode); paths.push_back(startNode); visited[0][0] = true; while (!unvisitedNeighbours.empty()) { node current = unvisitedNeighbours.front(); unvisitedNeighbours.pop(); // 到达终点,回溯路径并输出 if (current.pMain == make_pair(row - 1, col - 1)) { cout << "找到的路径坐标(从终点到起点):" << endl; pair<int, int> currPos = current.pMain; // 回溯父节点直到起点 while (currPos.first != -1 && currPos.second != -1) { cout << "(" << currPos.first << ", " << currPos.second << ")" << endl; // 在paths中查找父节点对应的节点 for (const auto& n : paths) { if (n.pMain == currPos) { currPos = n.parent; break; } } } // 想要从起点到终点的顺序,可以把路径存到临时vector里再反转输出 return true; } // 遍历四个方向的邻居 for (int i = 0; i < 4; ++i) { int newRow = current.pMain.first + dir[i][0]; int newCol = current.pMain.second + dir[i][1]; // 先判断坐标合法性,再判断是否可访问 if (newRow >= 0 && newRow < row && newCol >= 0 && newCol < col && !visited[newRow][newCol] && arr[newRow][newCol] != -1) { visited[newRow][newCol] = true; // 新节点的索引是paths当前的大小(因为马上要push进去) node newNode(make_pair(newRow, newCol), current.pMain, paths.size()); paths.push_back(newNode); unvisitedNeighbours.emplace(newNode); } } } // 没有找到有效路径 return false; } int main() { int arr[row][col] = { {0, 0, 0, -1, 0}, {-1, 0, 0, -1, -1}, {0, 0, 0, -1, 0}, {-1, 0, 0, 0, 0}, {0, 0, -1, 0, 0} }; if (findPath(arr)) { cout << "\n路径存在!" << endl; } else { cout << "不存在有效路径!" << endl; } return 0; }
代码关键说明
- 访问标记优化:用单独的
visited矩阵标记已访问节点,不会破坏原输入数组,更安全。 - 构造函数修正:用初始化列表初始化成员变量,避免局部变量覆盖成员变量的低级错误。
- 坐标判断顺序:先判断新坐标是否在矩阵范围内,再判断是否可访问,彻底避免数组越界问题。
- 路径回溯逻辑:通过节点的
parent坐标回溯,从终点倒推回起点,如果你需要从起点到终点的顺序,可以把路径存入临时vector后反转输出。 - 队列规范使用:严格遵循队列的FIFO特性,用
front()取队首、pop()弹出,避免错误用法。
补充:获取所有可能路径的思路
如果你需要获取所有可能的路径,而不仅仅是一条最短路径,BFS就不太合适了,推荐用DFS(深度优先搜索):
- 递归遍历每个可访问的邻居节点
- 每次访问时记录当前路径
- 到达终点时将当前路径保存到结果列表中
- 回溯时取消当前节点的访问标记,以便其他路径可以再次访问它
你可以写一个递归函数,参数包括当前坐标、当前路径、访问标记、结果列表,这样就能收集到所有合法路径啦。
备注:内容来源于stack exchange,提问作者Fox1942
相关产品推荐
相关产品推荐

