最短路径算法

两种经典的最短路径算法

1、迪杰斯特拉算法

算法思想:设置一个集合S记录已求得的最短路径的顶点,可以用数组s[]表示,初始化为0,当是s[vi]=1时,表示顶点vi放入S中,初始化时把v0放入S中。另外设置两个辅助数组
dist[]:记录顶点v0当其他顶点当前最短路径长度,dist[i]初始值为[v0][i];
path[]:path[i]表示从原点到顶点i之间的最短路径的前驱结点,在算法结束时,可以其值来追溯得到源点v0到vi之间的最短路径

算法步骤:
1、初始化:集合S初始化为{0},dist[]的初始值 dist[i] = edge[0][i],i=1,2,…n;
2、找出dist[]中最小值dist[j],将顶点j加入集合S,即修改s[vj] = 1;
3、修改从v0出发到集合V-S中任一顶点vk可到达的最短路径长度;如果dist[j] + edge[j][k] < dist[k],则令dist[k] = dist[j] + edge[j][k];
4、重复操作2、3步骤,操作n-1次,知道所有顶点都包含在S中

void dijkstra(MGraph G,int v,int dist[],int path[]){//v是源点下标
    int s[Maxsize];
    int min = 65535;//小技巧
    int u;
    //初始化s[],dist[],path[]
    for(int i=0;i<G.vexnum;i++){
        s[i] = 0;
        dist[i] = edge[v][i];
        if(G.edge[v][i]<min){
            path[i] = v;//与源点连通的顶点path存源点下标
        }
        else{
            path[i] = -1;//刚开始没有到源点路径的顶点path设置为-1
        }
    }
    s[v]=1;//源点加入结合s
    path[v]=-1;//源点不存在到自身的路径
    
    //核心代码
    for(int i=0;i<G.vexnum;i++){
        //找到剩余顶点中距离最小的顶点u,并把它加入到最短路径
        for(int j=0;j<G.vexnum;j++){
            if(s[j]!= 1 && dist[j]<min){
                min = dist[j];
                u = j;//u保存当前找到最短路径的下标
            }
        }
        s[u] = 1;//u是最小值,把它加入到最短路径
        
        //新加入顶点u来判断是否找到新的最短路径,如果有则更新
        for(int j=0;i<G.vexnum;j++){
            if(s[j]!=1 && dist[u]+edge[u][j] < dist[j]){
                dist [j] = dist[u]+edge[u][j];
                path[j] = u;//由顶点u过来
            }
        }
    }
}

算法分析:
核心部分是一个双重循环,这个双重循环的内循环两个并列的单重for循环组成,任意取其中一个循环中的操作作为基本操作,都可以得到时间复杂度为O(n的平方)

2、弗洛伊德算法

算法思想:
1、初始时,对于任意两个顶点vi到vj,若他们存在有向边,则以此边上的权值作为他们之间的最短路径长度;如他们之间不存在有向边,则以无穷大作为他们之间的最短路径长度。
2、逐步尝试在原路径中加入顶点k(k=0,1,…n-1)作为中间顶点,如果增加中间顶点后,得到的路径比原来的路径长度小,则更新此路径。
需要维护两个数组A,path,矩阵A用来记录当前任意两个顶点的最短长度。矩阵path用来记录当前两顶点间最短路径上要经过的中间顶点。

void Floyd(MGraph G,int path[][]){
    
    int A[MaxSize][MaxSize];
    //对A、path数组进行初始化
    for(int i=0;i<G.vexnum;i++){
        for(int j=0;j<G.vexnum;j++){
            A[i][j] = G.edge[i][j];
            path[i][j] = -1;
        }
    }
    
    //核心代码
    for(int k=0;k<G.vexnum;k++){
        for(int i=0;i<G.vexnum;i++){
            for(int j=0;j<G.vexnum;j++){
                if(A[i][k] + A[k][j] < A[i][j]){
                    A[i][j] = A[i][k] + A[k][j];
                    path[i][j] = k;
                }
            }
        }
    }
}

算法分析:
核心算法是三重循环,时间复杂度为O(n的三次方)

如果试题没有要求用哪种算法求最短路径,建议采用弗洛伊德算法,简洁明了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值