Dijkstra 算法的实现(算法笔记)

算法笔记:

 1) Dijkstra 算法的伪代码:

/**
    1) Dijkstra 算法的伪代码:
    void Dijkstra(G,d[],s)
    {
        初始化:
        for(循环 n 次)
        {
            u=使d[u] 最小的还未被访问的顶点的标号;
            记u为已被访问;
            for(从u 出发能达到的所有顶点)
            {
                if(v未被访问 && 以u为中介点使s到达v能使d[v]更优)
                    优化d[v];
            }
        }
    }

*/

2) Dijkstra 算法的邻接矩阵实现:
        时间复杂度:O(V*(V+V) = O(V^2);

/**
    2) Dijkstra 算法的邻接矩阵实现:
        时间复杂度:O(V*(V+V) = O(V^2);

    const int maxn = 1010;
    const int INF = 0x3fffffff;

    int Nv,G[maxn][maxn]; //Nv 是顶点数 ,G是邻接矩阵;
    int d[maxn]; //起点到达终点的最短路径长度
    bool hs[maxn] = {false};

    void Dijkstra(int s)
    {
        fill(d,d+maxn,INF); //初始化数组d;
        d[s] = 0; // 起点到达终点的距离;
        for(int i=0;i<Nv;++i)
        {
            int u=-1,MIN=INF;
            for(int j=0;j<Nv;++j)
            {
                if(hs[j]==false && d[j] < MIN)
                {
                    u=j;
                    MIN=d[j];
                }
            }

            if(u==-1)
                return;
            hs[u]=true;

            for(int v=0;v<Nv;++v)
            {
                if(hs[v]==false && G[u][v]!=INF && d[u]+G[u][v] < d[v] )
                    d[v] = d[u] + G[u][v];
            }
        }
    }
*/

3) Dijkstra 算法的邻接表实现:
        时间复杂度:O(V^2 + E);

/**
    3) Dijkstra 算法的邻接表实现:
        时间复杂度:O(V^2 + E);

    struct GNode
    {
        int v, dis; //v 为边的目标顶点,dis为边权
    }
    const int maxn = 1010;
    const int INF = 0x3fffffff;

    int Nv; //Nv 是顶点数 ,G是邻接矩阵;
    vector<Node> Adj[maxn];  //邻接表
    int d[maxn]; //起点到达终点的最短路径长度
    bool hs[maxn] = {false}; //标记数组

    void Dijkstra(int s)
    {
        fill(d,d+maxn,INF); //初始化数组d;
        d[s] = 0; // 起点到达终点的距离;
        for(int i=0;i<Nv;++i)
        {
            int u=-1,MIN=INF;
            for(int j=0;j<Nv;++j)
            {
                if(hs[j]==false && d[j] < MIN)
                {
                    u=j;
                    MIN=d[j];
                }
            }

            if(u==-1)
                return;
            hs[u]=true;

            for(int v=0;v<Adj[u].size();++v)
            {
                if(hs[v]==false && d[u]+Adj[u][v].dis < d[v] )
                    d[v] = d[u] + Adj[u][v].dis;
            }
        }
    }

*/

4) Dijkstra 算法的邻接矩阵实现:
        时间复杂度:O(V*(V+V) = O(V^2);

       如果要找出一条最短路径,并打印出这条路径该走的顶点编号,那么可以用一个 pre[maxn] 数组来存储;
       只需要在(2) 的基础上添加两个语句便可;

/**
    4) Dijkstra 算法的邻接矩阵实现:
        时间复杂度:O(V*(V+V) = O(V^2);

       如果要找出一条最短路径,并打印出这条路径该走的顶点编号,那么可以用一个 pre[maxn] 数组来存储;
       只需要在(2) 的基础上添加两个语句便可;

    const int maxn = 1010;
    const int INF = 0x3fffffff;

    int Nv,G[maxn][maxn]; //Nv 是顶点数 ,G是邻接矩阵;
    int d[maxn]; //起点到达终点的最短路径长度
    int pre[maxn]; //pre[v]表示从起点到v的路径上前驱顶点的编号; (新添加)
    bool hs[maxn] = {false};

    void Dijkstra(int s)
    {
        fill(d,d+maxn,INF); //初始化数组d;
        memset(pre,-1,sizeof(pre) ); // 初始化pre数组;(新添加)
        d[s] = 0; // 起点到达终点的距离;
        for(int i=0;i<Nv;++i)
        {
            int u=-1,MIN=INF;
            for(int j=0;j<Nv;++j)
            {
                if(hs[j]==false && d[j] < MIN)
                {
                    u=j;
                    MIN=d[j];
                }
            }

            if(u==-1)
                return;
            hs[u]=true;

            for(int v=0;v<Nv;++v)
            {
                if(hs[v]==false && G[u][v]!=INF && d[u]+G[u][v] < d[v] )
                {
                    d[v] = d[u] + G[u][v];
                    pre[v]=u; // 记录v的前驱顶点是 u;  (新添加)
                }
            }
        }
    }


    如果要得到起点到终点的路径:那么我们只需要从终点开始递归,每次函数内的递归参数传入pre[u] 的值即可;
    至于递归边界和递归式是什么:
    递归边界:pre[v] 的值是-1 的时候就到达了起点:
    递归式 :dfs(pre[v]);
    因此我们能得到递归函数:

    void dfs(int u)
    {
        if(pre[u] < -1 )    // 或者写为 if(u == st)
        {
            printf("%d\n",u);
            return;
        }
        else
        {
            dfs(pre[u]);
            printf("%d\n",u);
        }
    }
*/

5) 在找出起点到终点的距离最近的同时,也要使得起点到终点的边的权值之和最小,
       假定新增了边的权值(不只是距离);

        Dijkstra 算法的邻接矩阵实现:
        时间复杂度:O(V*(V+V) = O(V^2);


/**
    5) 在找出起点到终点的距离最近的同时,也要使得起点到终点的边的权值之和最小,
       假定新增了边的权值(不只是距离);

        Dijkstra 算法的邻接矩阵实现:
        时间复杂度:O(V*(V+V) = O(V^2);

    const int maxn = 1010;
    const int INF = 0x3fffffff;

    int Nv,G[maxn][maxn]; //Nv 是顶点数 ,G是邻接矩阵;
    int d[maxn]; //起点到达终点的最短路径长度
    int c[maxn]; // 起点到终点的最小消耗(花费);
    bool hs[maxn] = {false}; //顶点是否被选择;

    void Dijkstra(int s)
    {
        fill(d,d+maxn,INF); //初始化数组d;
        d[s] = 0; // 起点到达终点的距离;
        fill(c,c+maxn,INF); //求最小花费的时候,还是最好把花费数组初始化为INF;
        c[st] = 0; // 起点的花费为0

        for(int i=0;i<Nv;++i)
        {
            int u=-1,MIN=INF;
            for(int j=0;j<Nv;++j)
            {
                if(hs[j]==false && d[j] < MIN)
                {
                    u=j;
                    MIN=d[j];
                }
            }

            if(u==-1)
                return;
            hs[u]=true;

            for(int v=0;v<Nv;++v)
            {
                if(hs[v]==false && G[u][v]!=INF)
                {
                    if(d[u]+G[u][v] < d[v] )
                    {
                        d[v] = d[u] + G[u][v];
                        c[v] = c[u] + cost[u][v];
                    }
                    else if( d[u]+G[u][v] == d[v] && c[u] + cost[u][v] < c[v])
                        c[v] = c[u] + cost[u][v];
                }
            }
        }
    }

*/

6) 在找出起点到终点的距离最近的同时,也要使得起点到终点的点的权值之和最大,
       假定新增了顶点的权值;

        Dijkstra 算法的邻接矩阵实现:
        时间复杂度:O(V*(V+V) = O(V^2);

/**
    6) 在找出起点到终点的距离最近的同时,也要使得起点到终点的点的权值之和最大,
       假定新增了顶点的权值;

        Dijkstra 算法的邻接矩阵实现:
        时间复杂度:O(V*(V+V) = O(V^2);

    const int maxn = 1010;
    const int INF = 0x3fffffff;

    int Nv,G[maxn][maxn]; //Nv 是顶点数 ,G是邻接矩阵;
    int weight[maxn]; //顶点的权值;
    int d[maxn]; //起点到达终点的最短路径长度
    int w[maxn]; // 起点到终点的最大筹集物资;
    bool hs[maxn] = {false}; //顶点是否被选择;

    void Dijkstra(int s)
    {
        fill(d,d+maxn,INF); //初始化数组d;
        d[s] = 0; // 起点到达终点的距离;
        w[s] = weight[s];

        for(int i=0;i<Nv;++i)
        {
            int u=-1,MIN=INF;
            for(int j=0;j<Nv;++j)
            {
                if(hs[j]==false && d[j] < MIN)
                {
                    u=j;
                    MIN=d[j];
                }
            }

            if(u==-1)
                return;
            hs[u]=true;

            for(int v=0;v<Nv;++v)
            {
                if(hs[v]==false && G[u][v]!=INF)
                {
                    if(d[u]+G[u][v] < d[v] )
                    {
                        d[v] = d[u] + G[u][v];
                        w[v] = w[u] + weight[v];
                    }
                    else if( d[u]+G[u][v] == d[v] && w[u] + weight[v] > w[v]) //最短距离相同时看是否能使w[v]更优
                        w[v] = w[u] + weight[v];
                }
            }
        }
    }

*/

7) 在找出起点到终点的距离最近的同时,要求出最短路径条数;

        Dijkstra 算法的邻接矩阵实现:
        时间复杂度:O(V*(V+V) = O(V^2);

/**
    7) 在找出起点到终点的距离最近的同时,要求出最短路径条数;

        Dijkstra 算法的邻接矩阵实现:
        时间复杂度:O(V*(V+V) = O(V^2);

    const int maxn = 1010;
    const int INF = 0x3fffffff;

    int Nv,G[maxn][maxn]; //Nv 是顶点数 ,G是邻接矩阵;
    int d[maxn]; //起点到达终点的最短路径长度
    int num[maxn]; // 最短路径条数
    bool hs[maxn] = {false}; //顶点是否被选择;

    void Dijkstra(int s)
    {
        fill(d,d+maxn,INF); //初始化数组d;
        d[s] = 0; // 起点到达终点的距离;
        num[s] = 1;

        for(int i=0;i<Nv;++i)
        {
            int u=-1,MIN=INF;
            for(int j=0;j<Nv;++j)
            {
                if(hs[j]==false && d[j] < MIN)
                {
                    u=j;
                    MIN=d[j];
                }
            }

            if(u==-1)
                return;
            hs[u]=true;

            for(int v=0;v<Nv;++v)
            {
                if(hs[v]==false && G[u][v]!=INF)
                {
                    if(d[u]+G[u][v] < d[v] )
                    {
                        d[v] = d[u] + G[u][v];
                        num[v] = num[u];
                    }
                    else if( d[u]+G[u][v] == d[v] ) //最短距离相同时num[u] 与 num[v] 叠加
                        num[v]+=num[u];
                }
            }
        }
    }

*/

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值