Algorithm 迪克斯特拉';s寻路算法
我正在从一本书中学习寻路,但我发现了一些奇怪的说法 为了完整起见,我将包含大部分代码,但请跳到第二部分(Search())Algorithm 迪克斯特拉';s寻路算法,algorithm,Algorithm,我正在从一本书中学习寻路,但我发现了一些奇怪的说法 为了完整起见,我将包含大部分代码,但请跳到第二部分(Search()) 模板 类图 { 私人: //为图形使用的节点和边类型创建typedefs typedef typename图形_type::EdgeType Edge; typedef typename图形_type::NodeType节点; 私人: 常数图&u型&m图; //此向量包含构成最短路径树的边- //图的有向子树,它封装了来自 //SPT上的每个节点都连接到源节点。 std::
模板
类图
{
私人:
//为图形使用的节点和边类型创建typedefs
typedef typename图形_type::EdgeType Edge;
typedef typename图形_type::NodeType节点;
私人:
常数图&u型&m图;
//此向量包含构成最短路径树的边-
//图的有向子树,它封装了来自
//SPT上的每个节点都连接到源节点。
std::向量m_最短路径树;
//这是按节点索引索引到的,并保存最佳节点的总成本
//到目前为止找到的到给定节点的路径。例如,m_CostToThisNode[5]
//将保留组成最佳路径的所有边的总成本
//到目前为止在搜索中找到的节点5(如果节点5存在并且
//(当然有人参观过)。
std::向量m_CostToThisNode;
//这是指向节点的“父”边的索引(按节点)向量
//已连接到SPT,但尚未添加到SPT。
std::向量m_搜索边界;
国际资源;
int m_iTarget;
无效搜索();
公众:
图搜索Dijkstra(常数图类型和图,
int源,
int target=-1):m_图(Graph),
m_ShortestPathTree(graph.NumNodes()),
m_SearchFrontier(graph.NumNodes()),
m_CostToThisNode(graph.NumNodes()),
m_iSource(来源),
m_iTarget(目标)
{
搜索();
}
//返回定义SPT的边向量。如果给定目标
//在构造函数中,这将是包含所有节点的SPT
//在找到目标之前检查,否则它将包含所有节点
//在图表中。
std::vector getAllPath()常量;
//返回包含最短路径的节点索引向量
//从源到目标。它通过工作计算路径
//从目标节点向后通过SPT。
std::list GetPathToTarget()常量;
//将总成本返回到目标
双GetCostToTarget()常量;
};
搜索():
模板
void图_SearchDijkstra::Search()
{
//创建从最小到最大排序的索引优先级队列
//(从前到后)。请注意,iPQ中的最大元素数
//可能包含is NumNodes()。这是因为无法表示任何节点
//在队列中多次出现。
IndexedPriorityQLow pq(m_CostToThisNode,m_Graph.NumNodes());
//将源节点放在队列上
pq.插入件(m_iSource);
//而队列不是空的
而(!pq.empty())
{
//从队列中获取成本最低的节点。不要忘记返回值
//是*节点索引*,而不是节点本身。此节点是尚未创建的节点
//在距离源节点最近的SPT上
int NextClosestNode=pq.Pop();
//将此边从搜索边界移动到最短路径树
m_ShortestPathTree[NextClosestNode]=m_SearchFrontier[NextClosestNode];
//如果找到目标,请退出
if(NextClosestNode==m_itatarget)返回;
//现在来松弛边。对于每个连接到下一个最近节点的边
graph_type::ConstEdgeIterator ConstEdgeItr(m_graph,NextClosestNode);
for(const-Edge*pE=ConstEdgeItr.begin();
!ConstEdgeItr.end();
pE=ConstEdgeItr.next())
{
//此边指向的节点的总成本是
//当前节点加上连接它们的边的成本。
double NewCost=m_CostToThisNode[NextClosestNode]+pE->Cost();
//如果这一优势从未出现在前沿,请记下成本
//要到达它所指向的节点,请将边添加到边界
//以及PQ的目标节点。
如果(m_SearchFrontier[pE->To()]==0)
{
m_CostToThisNode[pE->To()]=新成本;
pq.插入(pE->To());
m_SearchFrontier[pE->To()]=pE;
}
//else测试以查看通过
//当前节点比目前发现的最便宜的成本低。如果
//如果将新成本分配给目的地,则此路径更便宜
//节点,更新其在PQ中的条目以反映更改,并添加
//边疆
else if((NewCostTo()]))&&
(m_ShortestPathTree[pE->To()]==0))
{
m_CostToThisNode[pE->To()]=新成本;
//由于成本比以前低,因此PQ必须
//我不得不对此作出解释。
更改优先级(pE->To());
m_SearchFrontier[pE->To()]=pE;
}
}
}
}
我不明白的是这部分:
//else test to see if the cost to reach the destination node via the
//current node is cheaper than the cheapest cost found so far. If
//this path is cheaper we assign the new cost to the destination
//node, update its entry in the PQ to reflect the change, and add the
//edge to the frontier
else if ( (NewCost < m_CostToThisNode[pE->To()]) &&
(m_ShortestPathTree[pE->To()] == 0) )
//else测试通过
//当前节点比目前发现的最便宜的成本更低。如果
//如果将新成本分配给目的地,则此路径更便宜
//节点,更新其在PQ中的条目以反映更改,并添加
//边疆
else if((NewCostTo()]))&&
(m_ShortestPathTree[pE->To()]==0))
如果新成本低于已发现的成本,那么为什么还要测试节点是否尚未添加到SPT?这似乎超出了检查的目的
仅供参考,在
m_ShortestPathTree[pE->To()]==0
中,容器是一个向量,其指针指向每个索引的边(或NULL)(该索引表示一个节点)想象下图
template <class graph_type>
void Graph_SearchDijkstra<graph_type>::Search()
{
//create an indexed priority queue that sorts smallest to largest
//(front to back). Note that the maximum number of elements the iPQ
//may contain is NumNodes(). This is because no node can be represented
// on the queue more than once.
IndexedPriorityQLow<double> pq(m_CostToThisNode, m_Graph.NumNodes());
//put the source node on the queue
pq.insert(m_iSource);
//while the queue is not empty
while(!pq.empty())
{
//get the lowest cost node from the queue. Don't forget, the return value
//is a *node index*, not the node itself. This node is the node not already
//on the SPT that is the closest to the source node
int NextClosestNode = pq.Pop();
//move this edge from the search frontier to the shortest path tree
m_ShortestPathTree[NextClosestNode] = m_SearchFrontier[NextClosestNode];
//if the target has been found exit
if (NextClosestNode == m_iTarget) return;
//now to relax the edges. For each edge connected to the next closest node
graph_type::ConstEdgeIterator ConstEdgeItr(m_Graph, NextClosestNode);
for (const Edge* pE=ConstEdgeItr.begin();
!ConstEdgeItr.end();
pE=ConstEdgeItr.next())
{
//the total cost to the node this edge points to is the cost to the
//current node plus the cost of the edge connecting them.
double NewCost = m_CostToThisNode[NextClosestNode] + pE->Cost();
//if this edge has never been on the frontier make a note of the cost
//to reach the node it points to, then add the edge to the frontier
//and the destination node to the PQ.
if (m_SearchFrontier[pE->To()] == 0)
{
m_CostToThisNode[pE->To()] = NewCost;
pq.insert(pE->To());
m_SearchFrontier[pE->To()] = pE;
}
//else test to see if the cost to reach the destination node via the
//current node is cheaper than the cheapest cost found so far. If
//this path is cheaper we assign the new cost to the destination
//node, update its entry in the PQ to reflect the change, and add the
//edge to the frontier
else if ( (NewCost < m_CostToThisNode[pE->To()]) &&
(m_ShortestPathTree[pE->To()] == 0) )
{
m_CostToThisNode[pE->To()] = NewCost;
//because the cost is less than it was previously, the PQ must be
//resorted to account for this.
pq.ChangePriority(pE->To());
m_SearchFrontier[pE->To()] = pE;
}
}
}
}
//else test to see if the cost to reach the destination node via the
//current node is cheaper than the cheapest cost found so far. If
//this path is cheaper we assign the new cost to the destination
//node, update its entry in the PQ to reflect the change, and add the
//edge to the frontier
else if ( (NewCost < m_CostToThisNode[pE->To()]) &&
(m_ShortestPathTree[pE->To()] == 0) )
S --5-- A --2-- F
\ /
-3 -4
\ /
B
Starting Weights: S(0), A(inf), B(inf), F(inf)
- Accept S
New weights: [S(0)], A(5), B(-3), F(inf)
- Accept B
New weights: [S(-3)], A(-7), [B(-3)], F(inf)
- Accept A
New weights: [S(-3)], [A(-7)], [B(-11)], F(-5)
- Accept B again
New weights: [S(-14)], [A(-18)], [B(-11)], F(-5)
- Accept A again
... infinite loop
Starting Weights: S(0), A(inf), B(inf), F(inf)
- Accept S
New weights: [S(0)], A(5), B(-3), F(inf)
- Accept B (doesn't change S)
New weights: [S(0)], A(-7), [B(-3)], F(inf)
- Accept A (doesn't change S or B
New weights: [S(0)], [A(-7)], [B(-3)], F(-5)
- Accept F