数据结构之最短路径的 Dijkstra Algorithm && Floyd Algorithm

本文探讨了数据结构中的两种最短路径算法——Dijkstra算法和Floyd算法。强调了最短路径问题与最小生成树的区别,指出最小生成树关注的是全联通图中所有路径之和最小的子树,而最短路径问题则专注于找到图中两点间路径之和最短的路径。

没有什么说的。代码中讲解的应该还算明确。

但是我想说的是一定要把最短路径和最小生成树给分开。。最小生成树是求一个Graph(这个图中必定是全部联通图)中,求解所有子树中所有路径之和最小的子树。。而最短路径则求Graph中是从一个点到另一个点路径之和最短的路径。这完全是两个问题。。没有任何联系!

#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <map>
#include <queue>
#include <stack>
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a));
#define For(a,b) for(int i = a;i<b;i++)
#define LL long long
#define MAX_N 100010
#define VN 10
using namespace std;
typedef int Vextype;
typedef int Adjtype;
typedef int Elemtype;
typedef struct
{
    Vextype vexs[VN];
    Adjtype arcs[VN][VN];
}Graph; //邻接矩阵的存储结构
typedef struct
{
    Adjtype length;
    int prevex;
}Path;//Dijkstra算法中的操作对象
typedef struct
{
    Adjtype weight[VN][VN];
    int nextVex[VN][VN];
}ShortPath;//Floyd算法中的操作对象
Elemtype Dijk_flag = 1;//判断该点是否到所有点都有通路的标志
Elemtype mark[VN][VN];//记录原始邻接矩阵的数据元素
/*

    初始化Dijkstra algorithm中的dis数组。
    其实也就是将0到Graph中所有的点的距离
    以及所有点的前驱(0),置于dis数组
    如果说没有通路。则置为-1。
*/
void init(Graph * graph,Path dis[],Elemtype node_num)
{
    dis[0].length = 0;
    dis[0].prevex = 0;
    graph->arcs[0][0] = 1;
    for(int i = 1; i<node_num; i++)
    {
        dis[i].length = graph->arcs[0][i];
        if(dis[i].length != MAX_N)
        {
            dis[i].prevex = 0;
        }
        else
            dis[i].prevex = -1;
    }
}
void Dijkstra(Graph * pgraph,Path dis[],Elemtype node_num)
{
    init(pgraph,dis,node_num);
    int minw,minVex;
    /*

        这个for循环每循环一次找到一个
        距离初始点的最短距离的点
    */
    for(int i = 1; i<node_num; i++)
    {
        minw = MAX_N;
        minVex = 0;
        /*

            该for循环是为了找到当前dis数组中最小的length值
        */
        for(int j = 1; j<node_num; j++)
        {
            if(pgraph->arcs[j][j] == 0 && dis[j].length < minw)
            {
                minw = dis[j].length;
                minVex = j;
            }
        }
        /*

            此判断是该Graph是否所有的点可以连成一个通路
            如果不能·则用全局变量Dijk_flag标记
        */
        if(minVex == 0)
        {
            Dijk_flag = 0;
            break;
        }
        pgraph->arcs[minVex][minVex] = 1;
        /*

            更新dis数组中剩下的元素中的前驱和length值
        */
        for(int j = 1; j<node_num; j++)
        {
            if(pgraph->arcs[j][j] == 0 && dis[j].length > dis[minVex].length + pgraph->arcs[minVex][j])
            {
                dis[j].length = dis[minVex].length + pgraph->arcs[minVex][j];
                dis[j].prevex = minVex;
            }
        }
    }
}
void Floyd(Graph *pgraph,ShortPath *ppath,Elemtype node_num)
{
    /*

        初始化ppath结构体中的数组元素。
        如果从i点到j点有通路,则nextVex[i][j] = j;
        否则等于-1。
        不论是否有通路,都将weight值赋予weight[i][j].

    */
    for(int i = 0; i<node_num; i++)
    {
        for(int j = 0; j<node_num; j++)
        {
            if(pgraph->arcs[i][j] != MAX_N)
            {
                ppath->nextVex[i][j] = j;
            }
            else
                ppath->nextVex[i][j] = -1;
            ppath->weight[i][j] = pgraph->arcs[i][j];
        }
    }
    /*

        每次外层循环k不变,就相当于喜欢是每次将k点插入i到j的路径当中去。
        这样遍历一遍求最短Graph中可以连通的点中。每两个点之间的最短路径。
    */
    for(int k = 0; k<node_num; k++)
        for(int i = 0; i<node_num; i++)
            for(int j = 0 ; j<node_num; j++){
                if(ppath->weight[i][k] >= MAX_N || ppath->weight[k][j] >= MAX_N)
                    continue;
                if(ppath->weight[i][j] > ppath->weight[i][k] + ppath->weight[k][j])
                {
                    ppath->weight[i][j] = ppath->weight[i][k] + ppath->weight[k][j];
                    ppath->nextVex[i][j] = ppath->nextVex[i][k];
                }
            }
}

int main()
{
    Graph pgraph;
    Path dis[VN];
    ShortPath shpath;
    int node_num = 6;
    int edge_num = 11;
    for(int i = 0; i<node_num; i++)
    {
        for(int j = 0; j<node_num; j++){
            if(i==j) mark[i][j] = 0;
            else mark[i][j] = MAX_N;
        }
    }
    int node_start,node_stop,edge_val = 0;
    for(int i = 0; i<edge_num; i++)
    {
        cin>>node_start>>node_stop>>edge_val;
        mark[node_start][node_stop] = edge_val;
    }
    /*

        为arcs邻接矩阵数组赋初值

    */
    for(int i = 0; i<node_num; i++)
    {
        for(int j = 0; j<node_num; j++)
        {
            pgraph.arcs[i][j] = mark[i][j];
        }
    }
    Dijkstra(&pgraph,dis,node_num);
    if(Dijk_flag)
    {
        cout<<"该图中所有的结点连通,且这是一个连通图。"<<endl<<endl;
    }
    else
        cout<<"这个图中存在不可访问到的结点,所以这不是一个连通图。"<<endl<<endl;
    cout<<"1 — 0的最短路径长度是: "<<endl<<dis[1].length<<endl<<endl;
    cout<<"1 — 0的最短路径是:"<<endl;
    cout<<"V_1 -> ";
    int prev = 1;
    while(1)
    {
        prev = dis[prev].prevex;
        cout<<"V_"<<prev<<" -> ";
        if(prev == 0)
        {
            cout<<endl<<endl;
            break;
        }
    }
    /*

        由于经过Dijkstra算法的调用,arcs数组中一些元素已被改变。
        所以需要再次对arcs数组进行初始化。

    */
    for(int i = 0; i<node_num; i++)
    {
        for(int j = 0; j<node_num; j++)
        {
            pgraph.arcs[i][j] = mark[i][j];
        }
    }
    Floyd(&pgraph,&shpath,node_num);
    cout<<"0 — 1的最短路径长度是: "<<endl<<shpath.weight[0][1]<<endl<<endl;
    cout<<"0 — 1的最短路径是:"<<endl;
    cout<<"V_0 -> ";
    int next = shpath.nextVex[0][1];
    while(1)
    {
        cout<<"V_"<<next<<" -> ";
        next = shpath.nextVex[next][1];
        if(next == 1)
        {
            cout<<"V_1"<<endl<<endl;
            break;
        }
    }
    //system("pause");
    return 0;
}
/*

2016.10.7

测试样例:

0 1 50
0 2 10
0 4 45
1 2 15
1 4 5
2 0 20
2 3 15
3 1 20
3 4 35
4 3 30
5 3 3

*/





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值