Dijkstra算法详解与C语言实现

2星 需积分: 47 22 下载量 198 浏览量 更新于2024-10-05 1 收藏 232KB DOC 举报
"这篇文档详细介绍了Dijkstra算法的原理,并提供了相关的代码示例。Dijkstra算法是一种用于寻找图中两点间最短路径的算法,由荷兰计算机科学家艾兹格·迪科斯彻提出。该算法适用于加权有向图或无向图,尤其在寻找最短路径时非常有效。" 在Dijkstra算法中,我们首先设置一个源点,然后逐步扩展最短路径到图中的其他点。算法的核心是维护一个优先队列(通常是基于最小堆),其中包含当前已知最短路径的顶点。每次从队列中取出具有最小路径长度的顶点,然后更新与其相邻且尚未加入最短路径集合的顶点的路径。 以下是Dijkstra算法的执行步骤: 1. 初始化:为所有顶点设置无限大的距离(除了源点设为0),并将它们放入优先队列中。 2. 取出优先队列中距离最小的顶点(源点)。 3. 更新与该顶点相邻的其他顶点的距离,如果通过当前顶点到达这些顶点的路径比已知的路径更短,则更新距离。 4. 将更新后的顶点放入优先队列中。 5. 重复步骤2-4,直到优先队列为空或者目标顶点已被处理。 6. 最终,所有顶点的最短路径信息将被计算出来。 在提供的代码示例中,`Dijkstra.c`包含了算法的实现。`struct Point`定义了图中的顶点,包含顶点标识和指向相邻顶点的链接;`struct Link`表示边,包括顶点信息和边的权重;`struct Table`是工作表,存储每个顶点的最短路径信息。`Dijkstra()`函数是算法的主体,它接收图的顶点结构和工作表作为参数,返回最短路径的计算结果。`FindSmallest()`函数用于在工作表中找到当前最短路径的顶点。 输入和输出格式按照特定的约定,例如,输入时需要按编号指定算法的起始点,输出则会显示从起点到各个顶点的最短路径。`CreateTable()`用于创建工作表,`PrintTable()`和`PrintPath()`分别用于打印工作表和最短路径。 这个文档提供了一个完整的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; }