Algorithm 迪克斯特拉';s寻路算法

Algorithm 迪克斯特拉';s寻路算法,algorithm,Algorithm,我正在从一本书中学习寻路,但我发现了一些奇怪的说法 为了完整起见,我将包含大部分代码,但请跳到第二部分(Search()) 模板 类图 { 私人: //为图形使用的节点和边类型创建typedefs typedef typename图形_type::EdgeType Edge; typedef typename图形_type::NodeType节点; 私人: 常数图&u型&m图; //此向量包含构成最短路径树的边- //图的有向子树,它封装了来自 //SPT上的每个节点都连接到源节点。 std::

我正在从一本书中学习寻路,但我发现了一些奇怪的说法

为了完整起见,我将包含大部分代码,但请跳到第二部分(Search())

模板
类图
{
私人:
//为图形使用的节点和边类型创建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