C++ 在有向图中通过bfs搜索显示最短路径
我一直在为大学做一个项目,遇到了一个相当大的问题。我要做一个函数,通过一个有向图,从点a到点B,得到最短路径,并按顺序显示路径 例如,如果节点拥有一个州名,并且我们想要找到加利福尼亚州和犹他州之间的最短路径,那么输出将显示California->nevada->Utah 目前,我的遍历显示了使用bfs搜索的所有节点,而不是从A点到B点的节点列表 以下是我执行任务的情况。我唯一真正的问题是,我如何跟踪我实际遍历的节点,而不是搜索的所有节点C++ 在有向图中通过bfs搜索显示最短路径,c++,algorithm,graph-theory,C++,Algorithm,Graph Theory,我一直在为大学做一个项目,遇到了一个相当大的问题。我要做一个函数,通过一个有向图,从点a到点B,得到最短路径,并按顺序显示路径 例如,如果节点拥有一个州名,并且我们想要找到加利福尼亚州和犹他州之间的最短路径,那么输出将显示California->nevada->Utah 目前,我的遍历显示了使用bfs搜索的所有节点,而不是从A点到B点的节点列表 以下是我执行任务的情况。我唯一真正的问题是,我如何跟踪我实际遍历的节点,而不是搜索的所有节点 bool DirectedGraph::GetShorte
bool DirectedGraph::GetShortestPath(
const string& startNode, const string& endNode,
bool nodeDataInsteadOfName, vector<string>& traversalList) const
{
//Nodes are the same
if (startNode.compare(endNode) == 0)
return false;
//Stores the location of our nodes in the node list
vector<int> path;
//Queue to hold the index of the node traversed
queue<int> q;
//Create our boolean table to handle visited nodes
bool *visited = new bool[m_nodes.size()];
//initialize bool table
memset(visited, false, sizeof(bool) * m_nodes.size());
//Label the start node as visited
visited[GetNodeIndex(startNode)] = true;
//Push the node onto our queue
q.push(GetNodeIndex(startNode));
while (!q.empty())
{
//Store the nodes index
int index = q.front();
path.push_back(q.front());
q.pop();
int i = 0;
for (i = 0; i < m_nodes[index]->Out.size(); i++)
{
//If this node matches what we are looking for break/return values
if (m_nodes[index]->Out[i]->targetI == GetNodeIndex(endNode))
{
path.push_back(m_nodes[index]->Out[i]->targetI);
if (nodeDataInsteadOfName)
{
path.push_back(m_nodes[index]->Out[i]->targetI);
for (int x = 0; x < path.size(); x++)
{
traversalList.push_back(m_nodes[path[x]]->Data);
}
}
else
{
for (int x = 0; x < path.size(); x++)
{
traversalList.push_back( m_nodes[path[x]]->Name);
}
}
return true;
}
//Continue through the data
if (!visited[m_nodes[index]->Out[i]->targetI])
{
visited[m_nodes[index]->Out[i]->targetI] = true;
q.push(m_nodes[index]->Out[i]->targetI);
}
}
}
// You must implement this function
return false;
}
bool DirectedGraph::GetShortestPath(
常量字符串和起始节点,常量字符串和结束节点,
bool nodedaintosteofname、vector和traversalList)const
{
//节点是相同的
if(startNode.compare(endNode)==0)
返回false;
//在节点列表中存储节点的位置
向量路径;
//用于保存所遍历节点的索引的队列
队列q;
//创建布尔表以处理访问的节点
bool*visted=新bool[m_nodes.size()];
//初始化布尔表
memset(已访问,false,sizeof(bool)*m_nodes.size());
//将开始节点标记为已访问
已访问[GetNodeIndex(startNode)]=true;
//将节点推到我们的队列中
q、 推送(GetNodeIndex(startNode));
而(!q.empty())
{
//存储节点索引
int index=q.front();
路径。向后推(q.front());
q、 pop();
int i=0;
对于(i=0;iOut.size();i++)
{
//如果此节点与我们要查找的中断/返回值匹配
if(m_节点[index]->Out[i]->targetI==GetNodeIndex(endNode))
{
path.push_back(m_节点[index]->Out[i]->targetI);
if(nodedaintainsteadofname)
{
path.push_back(m_节点[index]->Out[i]->targetI);
对于(int x=0;x数据);
}
}
其他的
{
对于(int x=0;xName);
}
}
返回true;
}
//继续浏览数据
如果(!访问了[m_节点[index]->Out[i]->targetI])
{
已访问的[m_节点[index]->Out[i]->targetI]=true;
q、 推送(m_节点[index]->Out[i]->targetI);
}
}
}
//您必须实现此功能
返回false;
}
//图私有成员的定义
struct Edge
{
int srcI; // Index of source node
int targetI; // Index of target node
Edge(int sourceNodeIndex, int targetNodeIndex)
{
srcI = sourceNodeIndex;
targetI = targetNodeIndex;
}
};
struct Node
{
string Name;
string Data;
Node(const string& nodeName, const string& nodeData)
{
Name = nodeName;
Data = nodeData;
}
// List of incoming edges to this node
vector<Edge*> In;
// List of edges going out from this node
vector<Edge*> Out;
};
// We need a list of nodes and edges
vector<Node*> m_nodes;
vector<Edge*> m_edges;
// Used for efficiency purposes so that quick node lookups can be
// done based on node names. Maps a node name string to the index
// of the node within the nodes list (m_nodes).
unordered_map<string, int> m_nodeMap;
struct-Edge
{
int srcI;//源节点的索引
int targetI;//目标节点的索引
边缘(int sourceNodeIndex、int targetNodeIndex)
{
srcI=源节点索引;
targetI=targetNodeIndex;
}
};
结构体类型
{
字符串名;
字符串数据;
节点(常量字符串和节点名、常量字符串和节点数据)
{
名称=节点名称;
数据=节点数据;
}
//此节点的传入边列表
矢量输入;
//从此节点引出的边的列表
矢量输出;
};
//我们需要一个节点和边的列表
向量m_节点;
向量m_边;
//用于提高效率,以便可以进行快速节点查找
//根据节点名称完成。将节点名称字符串映射到索引
//节点列表中节点的名称(m_节点)。
无序地图m_节点地图;
第一个问题是for循环中的if问题。路径变量只能包含两项:开始节点和结束节点。我建议您不要使用for循环跟踪路径。而是为每个节点指定一个距离
struct Node
{
string Name;
string Data;
int Distance;
Node(const string& nodeName, const string& nodeData)
{
Name = nodeName;
Data = nodeData;
Distance = INT_MAX;
}
// List of incoming edges to this node
vector<Edge*> In;
// List of edges going out from this node
vector<Edge*> Out;
};
在每次迭代中,从队列中选择一个节点(称之为索引),循环遍历其邻接列表(传出弧),并测试是否访问了相邻节点。如果访问了该节点,请跳过它。如果未访问该节点,请将其距离设置为
m_nodes[index]->Distance + 1
更新每个节点的距离后,检查它是否是最终节点,如果是,则断开循环
此时,距离已正确更新。从结束节点向后移动,每次使用(距离=当前节点的距离-1)从邻接列表中选择节点时。您可以使用m_边向量来执行此操作,每次您实际知道targetI,因此您可以使用上面提到的距离值检查其对应的scrI。如果在遍历图形时,您记得到达所遍历的每个节点所需的步数,然后在最后,你可以反向工作,以获得最短的路径。如果你发现你的目标节点距离为n,那么它与距离为n-1的节点相邻,与距离为n-2的节点相邻,等等,一直到距离为0的起始节点。你的意思是像Dijkstra的算法一样?我已经试着修改上面的代码来做你所说的,我似乎想不出一种方法来正确地存储n值。我肯定我一定错过了什么,因为这似乎应该是一个相当简单的修复。
m_nodes[index]->Distance + 1