Dijkstra算法流程图详解:最短路径计算与实现

5星 · 超过95%的资源 需积分: 50 60 下载量 70 浏览量 更新于2024-09-12 收藏 165KB DOC 举报
Dijkstra算法是一种用于解决最短路径问题的高效算法,其核心思想是基于贪心策略,通过逐步缩小待解决区域,找到从起点到各个终点的最短路径。下面是该算法的详细流程图和实现过程: 1. **需求与规格说明**: - Dijkstra算法适用于求解无向或有向加权图中,从一个指定的源节点(通常标记为`s`)到图中所有其他节点的最短路径。 - 算法采用分治策略,从起点开始,每次选择未被访问过的邻居节点中距离起点最近的一个,更新其到起点的距离。 2. **算法实现**: - 使用邻接矩阵作为图的数据结构,存储节点间边的权重,其中`w[u, v]`表示从节点`u`到节点`v`的边的权重。 - 初始化阶段,设置源节点`s`的`dist[s]`为0,其他所有节点的`dist`值为无穷大,标记为未扩展状态。 - 主循环会进行`n-1`次迭代(`n`为图中节点总数),每次迭代: a. 找到当前未扩展且距离最小的节点`u`,将其标记为已扩展。 b. 遍历`u`的所有邻接节点`v`,如果通过`u`到达`v`的路径(`dist[u] + w[u, v]`)比`v`当前的`dist[v]`要短,则更新`dist[v]`。 c. 更新`v`的前一个节点为`u`,表示这条路径是由`u`发现的。 3. **用户交互与功能**: - 用户输入图的边权重信息,以及要查询的两个顶点,程序会自动计算并输出这两点间的最短路径。 - 关键在于初始化阶段,正确地设置二维数组以反映实际图的边和权重。 4. **设计思想**: - 算法利用优先队列(如二叉堆)辅助实现,确保每次选取距离最小的节点,从而保证搜索路径的有效性。 - 最终目标是找出所有节点对的最短路径,但实际过程中,算法只关心从`s`到其他节点的路径。 5. **源代码**: - 提供了一个C语言的示例代码,包含必要的头文件导入,展示了如何使用邻接矩阵数据结构、初始化`dist`数组以及执行Dijkstra算法的主要逻辑。 总结来说,Dijkstra算法通过分阶段处理图中的节点,不断优化路径估计,直到找到所有节点的最短路径。理解这个流程图并结合实际代码,可以有效地在实际项目中应用此算法来解决最短路径问题。
997 浏览量
讲解 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; }