Dijkstra(迪杰斯特拉算法)的C++实现,附源码及解释

介绍

        迪杰斯特拉算法,是求从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。

大体思路

  1. 初始化:设置一个集合S,用于存储已经找到最短路径的顶点。初始时,S只包含源点。同时,创建一个数组dist[]来存储从源点到每个顶点的最短路径权重,初始时除了源点的dist值为0,其他所有顶点的dist值设为无穷大(表示尚未找到路径)。

  2. 选择最小距离顶点:从未加入S的顶点集合中,选择一个dist[]值最小的顶点u,作为当前顶点。

  3. 松弛操作:对当前顶点u的所有邻接顶点v,进行松弛操作。如果通过顶点u到达邻接顶点v的路径权重小于当前记录的dist[v],则更新dist[v]为新的更小的权重,并且更新path[v]为当前顶点u

  4. 更新集合S:将当前顶点u加入到集合S中,表示已经找到了从源点到顶点u的最短路径。

  5. 重复过程:重复步骤2和3,直到所有顶点都被加入到集合S中,或者当选择出的最小dist[]值不再改变时(表示没有更短的路径可以找到)。

  6. 路径回溯:如果需要输出从源点到某个特定顶点的最短路径,可以通过path[]数组回溯来构建路径。

实现步骤

         头文件

        

        1.0结构体定义

        

        2.0 辅助容器

        其中visited容器是为了判断点是否已经经过过。

        dist数组则记录了,初始顶点到目标顶点的距离。(是初始顶点,比如路径0-2-3,那么dist[3]是从0到2到3的路径距离) 。

        path数组则记录了当前顶点的父顶点。我们就是通过父节点来抽象的将顶点加入路径的。最后还可以通过父顶点一路回溯,输出路径。

        3.0迪杰斯特拉算法

        整体框架类似于普里姆算法(Prim算法,这一章中有对内外循环以及u=-1的解释)。贪心算法的思想,依次优先将小值点“访问”(visit),再更新与相邻顶点dist的值。

        4.0初始化,添加边以及输出操作 

        打印输出操作中,利用的栈先进后出的特点,依次逆序将路径中的顶点压入栈中,最后依次弹出,输出顺序即为路径的顺序。

        本片内容旨在提供迪杰斯特拉的算法c++实现,至于代码中没有对指针进行后续管理比如delete操作,不作赘述。 

        最后提醒一句,在当前代码中,Dijkstra(v)表示,以v为起始点,构建最短路径;print(u)表示从起始点到u点的路径及权重。

源代码

#include<iostream>
#include<vector>
#include<climits>

class ALGraph{
    private:
        struct Edge{
            int target;//顶点索引
            int weight;//权重
            Edge*next;//
        };


    public:
        int V;//顶点数量
        std::vector<Edge*>adj;
        std::vector<bool>visited;
        std::vector<int>dist;
        std::vector<int>path;
        
        //初始化
        ALGraph(int V):V(V),adj(V,nullptr),visited(V,false),dist(V,INT_MAX),path(V,-1){}
        //添加边
        void AddEdge(int a,int b,int weight = 0){
            Edge*edge = new Edge{b,weight,adj[a]};
            adj[a] = edge;  
        }
        //迪杰斯特拉
        void Dijkstra(int v){
            
            dist[v] = 0;
            
            for(int i =0;i<V;i++){
                int u = -1;
                
                for(int k = 0;k<V;k++){
                    
                    if(!visited[k]&&(u==-1||dist[k]<dist[u])){
                        u = k;
                    }
                }

                visited[u] = true;

                for(Edge*p = adj[u];p!=nullptr;p = p->next){
                    int target = p->target;
                    if(!visited[target]&&(dist[target]>dist[u]+p->weight)){
                        path[target] = u;
                        dist[target] = dist[u]+p->weight;
                    }
                }
            }
            
        }
        //打印输出
        void print(int t){
            
            std::vector<int>pathstack;
            int current = t;
            while(path[current]!=-1){
                pathstack.push_back(current);
                current = path[current];
            }
            pathstack.push_back(current);
            while (!pathstack.empty()) {
                std::cout << pathstack.back();
                if (pathstack.size() > 1) std::cout << "-->";
                pathstack.pop_back();
            }
            std::cout << "=="<< dist[t] << std::endl; // 打印总权重
        }      
};

int main()
{

    ALGraph g(5);
    g.AddEdge(0,1,10);
    g.AddEdge(0,3,7);
    g.AddEdge(0,4,5);
    g.AddEdge(1,2,6);
    g.AddEdge(1,4,2);
    g.AddEdge(2,3,6);
    g.AddEdge(2,4,9);
    g.AddEdge(3,4,2);
    
    g.Dijkstra(0);
    g.print(2);
    return 0;
}

        举例验证,结果正确。 

  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dijkstra迪杰斯特拉算法是一种典型的最短路径算法,可以用于计算一个节点到其他节点的最短路径。它的主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止,使用的是广度优先搜索的思想。该算法通过不断更新起始点到其他节点的距离,选择当前距离最短的节点进行扩展,直到所有节点都被扩展完毕,找到起始点到其他节点的最短路径。Dijkstra算法在网络路由、地图导航等领域有广泛应用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++实现Dijkstra(迪杰斯特拉)算法](https://download.csdn.net/download/weixin_38692122/12724830)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Dijkstra(迪杰斯特拉)算法](https://blog.csdn.net/qq_43461641/article/details/100632351)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [DijkstraAlgorithm(迪杰斯特拉算法)](https://blog.csdn.net/qq_45740348/article/details/113575420)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值