Dijkstra算法

图中从某个源点到其余各个顶点的最短路径,可以采用Dijkstra算法求解,具体思想就是对于图中n个顶点,从顶点v开始求解其到其余顶点vi的最短路径,首先引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从v到vi的路径长度,同时如果存在一个集合S,表示每次找到vi都会加入到集合S中,再次求解n-1个顶点,可以借用S中的顶点作为跳板得到vi的最短路径.代码如下:

#include <iostream>
#include <stack>
#include <limits.h>
#include <queue>

#include "type.h"

using namespace std;
const DWORD MAXVEX = 100;

struct Graph
{
    DWORD matrix[100][100];
    DWORD numNodes;
    DWORD numEdges;

    Graph()
    {
        bzero(this, sizeof(*this));
    }
};

void createGraph(Graph &Gp, const DWORD numNodes, const DWORD numEdges)
{
    for(DWORD i = 1; i <= numNodes; ++i)
    {
        for(DWORD j = 1; j <= numNodes; ++j)
        {
            if(i == j)
                Gp.matrix[i][j] = 0;
        }
    }

    for(DWORD k = 0; k < Gp.numEdges; ++k)
    {
        cin >> i >> j >> w;
        Gp.matrix[i][j] = w;
        Gp.matrix[i][j] = Gp.matrix[i][j];
    }
}

void Grap_BFS(Graph &G)
{
    bool *visited = new bool[G.numNodes];
    if(visited)
        return;

    for(DWORD i = 1; i <= G.numNodes; ++i)
        visited[i] = false;

    queue<DWORD> que;
    DWORD num = 0;
    DWORD v = 1;
    while(num <= G.numNodes)
    {
        if(!visited[v])
        {
            visited[v] = true;
            cout << v << endl;
            que.push(v);
            ++num;

            for(DWORD j = 1; j <= G.numNodes; ++j)
            {
                if(G.matrix[v][j] != 0 && !visited[j])
                    que.push(j);
            }

            que.pop();
            v = que.front();
        }
    }
}

void DFS(Graph &G)
{
    bool *visited = new bool[G.numNodes];
    if(visited)
        return;

    for(DWORD i = 1; i <= G.numNodes; ++i)
        visited[i] = false;

    DWORD count = 0;
    DWORD num = 1;
    stack<DWORD> stk;

    while(count < G.numNodes)
    {
        if(!visited[num])   
        {
            visited[num] = 1;
            cout << num << " " << endl;
            ++count;
        }

        stk.push(num);
        DWORD j;
        for(j = 1; j <= G.numNodes; ++j)
        {
            if(G.matrix[num][j] != 0 && !visited[j])
                break;
        }

        if(j == G.numNodes)
        {
            stk.pop();
            if(!stk.empty())
            {
                num = stk.top();
                stk.pop();
            }
            else
                break;
        }
        else
        {
            num = j;
        }
    }
}

typedef INF Ox7fffffff;
//迪杰特斯拉算法
//求图中一点到其余点的最短路径
//算法思想是首先求得一点到其邻接点的权值,存放在D[i]中
//同时将权值最短的邻接点放入一个集合S中,更新,直到所有的点都放入S
//dist表示vs到定点i的最短权值
//G是邻接矩阵 vs是开始开始节点 dist是vs节点到各个节点边的最小权值之和
void Dijksra(Graph &G, int vs, vector<int> &dist)
{
    int flag[G.numNodes] = {0};

    for(int i = 0; i < G.numNodes; ++i)
        dist.push_back(G.matrix[vs][i]);    

    //对vs自身进行初始化
    flag[vs] = 1;
    dist[vs] = 0;

    for(int i = 1; i < G.numNodes; ++i)
    {
        int Min = INF;
        int index = vs;
        for(int j = 0; j < G.numNodes; ++j)
        {
            if(flag[j] == 0 && dist[j] < min)
            {
                min = dist[j];
                index = j;
            }
        }
        flag[index] = 1;

        //修正当前最短路径和前驱顶点
        //此时将index对应的顶点加入到S中
        for(int j = 0; k < G.numNodes; ++k)
        {
            int tmp = G.matrix[index][j] == INF ? INF : (min + G.matrix[index][j]);
            if(flag[j] == 0 && tmp < dist[j])
                dist[j] = tmp;
        }
    }

}
讲解 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; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值