Dijkstra算法详解:寻找最短路径

需积分: 10 0 下载量 200 浏览量 更新于2024-08-22 收藏 2.81MB PPT 举报
"本文主要介绍了迪杰斯特拉(Dijkstra)算法的思想,并将其应用于图论中的最短路径问题。Dijkstra算法是一种解决单源最短路径问题的算法,尤其适用于加权有向图。同时,文章还提及了图的基本概念,如有向图、无向图、完全图以及图的各种性质,如顶点的度、路径和环等。" Dijkstra算法是图论中的一个重要算法,由荷兰计算机科学家艾兹格·迪杰斯特拉在1956年提出,主要用于寻找图中一个起点到其他所有顶点的最短路径。这个算法的关键在于它按路径长度递增的顺序逐步确定最短路径。具体步骤如下: 1. 初始化:设置一个源点V0,创建两个集合S(初始为空)和T(包含所有其他顶点)。S用于存储已找到最短路径的顶点,T则存储待处理的顶点。为所有顶点分配距离值,V0的距离值设为0,其他顶点的距离值设为无穷大。 2. 找到T中距离值最小的顶点u,并将其加入S。更新与u相邻的所有顶点v的距离值,如果通过u到达v的路径比当前记录的最短路径更短,则更新v的距离值。 3. 重复步骤2,直到S包含了所有顶点,或者T为空。此时,所有顶点到源点V0的最短路径都已找到。 图是一种数据结构,由顶点(节点)和边(连接顶点的关系)组成。有向图的边具有方向,表示从一个顶点到另一个顶点的流向,而无向图的边没有方向,表示两个顶点之间的相互关系。无向图的边通常表示为顶点对(v, w),而有向图的边表示为弧(<v, w>),其中v是弧尾,w是弧头。 图的度是衡量一个顶点连接程度的指标。在无向图中,一个顶点的度是与其相连的边的数量。而在有向图中,度分为入度(作为弧头的边数量)和出度(作为弧尾的边数量)。一个有n个顶点的有向图最多有n(n-1)条边,无向图最多有n(n-1)/2条边。 路径是图中一连串相邻接的顶点,环或回路则是起始于并终止于同一顶点的路径。路径的长度可以是边的数量,也可以是路径上各边权重的总和。在网络和路由问题中,这些概念尤为重要,Dijkstra算法就是解决这类问题的有效工具。 总结来说,Dijkstra算法是一种高效且广泛应用的算法,特别是在寻找图中单源最短路径的问题上。结合图的基本概念,我们可以更好地理解和应用这个算法解决实际问题。
2009-10-28 上传
讲解 Dijkstra 算法的基本思想,另外还有算法实现. 当然了,这个算法当路径点上万的时候效率上会降低。 我有另外的改进实现, 上万个点也是在200毫秒内完成。但是不知道怎么添加, 我只能在这里贴关键代码了 : static std::list<Node*> vecNodes; static std::list<Edge*> vecEdges; bool CDijkstras::DijkstrasFindPath(Node* psrcNode, Node* pdstNode, std::list<Node*>& vec, double& fromSrcDist) { if (psrcNode == 0 || pdstNode == 0) return false; if (psrcNode == pdstNode) { vec.push_back(pdstNode); return false; } std::list<Node*>::const_iterator it; for (it=vecNodes.begin(); it!=vecNodes.end(); it++) { (*it)->bAdded = false; (*it)->previous = 0; (*it)->distanceFromStart = MAXDOUBLE; (*it)->smallest = 0; } bool bFindDst = DijkstrasRouteInitialize(psrcNode, pdstNode); fromSrcDist = pdstNode->distanceFromStart; Node* previous = pdstNode; while (previous) { vec.push_back(previous); previous = previous->previous; } m_pDstNode = pdstNode; return bFindDst; } bool CDijkstras::DijkstrasRouteInitialize(Node* psrcNode, Node* pdstNode) { bool bFindDst = false; psrcNode->distanceFromStart = 0; Node* smallest = psrcNode; smallest->bAdded = true; std::list<Node*>::const_iterator it, ait; std::list<Node*> AdjAdjNodes ; for (it=psrcNode->connectNodes.begin(); it!=psrcNode->connectNodes.end(); it++) { if ((*it)->bAdded) continue; (*it)->smallest = psrcNode; (*it)->bAdded = true; AdjAdjNodes.push_back(*it); } while (1) { std::list<Node*> tempAdjAdjNodes; for (it=AdjAdjNodes.begin(); it!=AdjAdjNodes.end(); it++) { Node* curNode = *it; for (ait=curNode->connectNodes.begin(); ait!=curNode->connectNodes.end(); ait++) { Node* pns = *ait; double distance = Distance(pns, curNode) + pns->distanceFromStart; if (distance < curNode->distanceFromStart) { curNode->distanceFromStart = distance; curNode->previous = pns; } if (pns->bAdded == false) { tempAdjAdjNodes.push_back(pns); pns->bAdded = true; } } if (curNode == pdstNode) { bFindDst = true; } } if (bFindDst) break; if (tempAdjAdjNodes.size() == 0) break; AdjAdjNodes.clear(); AdjAdjNodes = tempAdjAdjNodes; } return bFindDst; } // Return distance between two connected nodes float CDijkstras::Distance(Node* node1, Node* node2) { std::list<Edge*>::const_iterator it; for (it=node1->connectEdges.begin(); it!=node1->connectEdges.end(); it++) { if ( (*it)->node1 == node2 || (*it)->node2 == node2 ) return (*it)->distance; } #ifdef _DEBUG __asm {int 3}; #endif return (float)ULONG_MAX; } /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ //得到区域的Key// __int64 CDijkstras::GetRegionKey( float x, float z ) { long xRegion = (long)(x / m_regionWidth); long zRegion = (long)(z / m_regionHeight); __int64 key = xRegion; key <<= 32; key |= ( zRegion & 0x00000000FFFFFFFF ); return key; } //得到区域的Key// __int64 CDijkstras::GetRegionKey( long tx, long tz ) { long xRegion = tx ; long zRegion = tz ; __int64 key = xRegion; key <<= 32; key |= ( zRegion & 0x00000000FFFFFFFF ); return key; } //取得一个区域内的所有的路径点, 返回添加的路径点的个数// unsigned long CDijkstras::GetRegionWaypoint (__int64 rkey, std::vector<Node*>& vec) { unsigned long i = 0; SAME_RANGE_NODE rangeNode = mmapWaypoint.equal_range(rkey); for (CRWPIT it=rangeNode.first; it!=rangeNode.second; it++) { i++; Node* pn = it->second; vec.push_back(pn); } return i; } inline bool cmdDistanceNode (Node* pNode1, Node* pNode2) { return pNode1->cmpFromStart < pNode2->cmpFromStart; }; //添加一个路径点// Node* CDijkstras::AddNode (unsigned long id, float x, float y, float z) { Node* pNode = new Node(id, x, y, z); __int64 rkey = GetRegionKey(x, z); mmapWaypoint.insert(make_pair(rkey, pNode)); mapID2Node[id] = pNode; return pNode; } //添加一条边// Edge* CDijkstras::AddEdge (Node* node1, Node* node2, float fCost) { Edge* e = new Edge (node1, node2, fCost); return e; } //通过路径点ID得到路径点的指针// Node* CDijkstras::GetNodeByID (unsigned long nid) { std::map<unsigned long, Node*>::const_iterator it; it = mapID2Node.find(nid); if (it!=mapID2Node.end()) return it->second; return NULL; }