最短路径(图)

最短路径问题:

一、源点到其余顶点的最短路径
二、每一对顶点之间的最短路径

一、迪杰斯特拉算法(Dijkstra)

Dijkstra: 解决单源最短路径,按路径长度递增的次序产生最短路径的算法。*主要找出当前源点到其他顶点最短的一条路径,再利用此路径更新源点至各顶点的最小路径,循环往复直至源点到各顶点均为最短路径。

定义邻接矩阵及辅助数组

#include<stdbool.h>
#define MAXSIZE 100
#define INF 0x3f3f3f3f
//邻接矩阵
typedef struct
{
    char vexs[MAXSIZE];
    int arcs[MAXSIZE][MAXSIZE];
    int vexnum,arcnum;
}AMGraph;
bool S[MAXSIZE];//是否确定最短路径长度
int D[MAXSIZE];//记录当前最短路径长度
int P[MAXSIZE];//终点直接前驱顶点序号

Dijkstra算法

void Dijkstra(AMGraph G,int v)
{
    int n=G.vexnum,i,j,l,min;
    for(i=0;i<n;i++)
    {
        S[i]=false;
        D[i]=G.arcs[v][i];
        if(D[i]<INF)
        {
            P[i]=v;
        }
        else
        {
            P[i]=-1;
        }
    }
    S[v]=true;
    D[v]=0;
    for(i=0;i<n;i++)
    {
        min=INF;
        for(j=0;j<n;j++)
        {
            if(D[j]<min&&!S[j])
            {
                l=j;
                min=D[j];
            }
        }
        S[l]=true;
        for(j=0;j<n;j++)
        {
            if((D[l]+G.arcs[l][j])<D[j]&&!S[j])
            {
                D[j]=D[l]+G.arcs[l][j];
                P[j]=l;
            }
        }
    }
    return ;
}

时间复杂度:O(n^2)

二、弗洛伊德算法(Floyd)

Floyd:解决多源最短路径,形式上比Dijkstra更容易理解,因此更适合解多源最短路径。 依次利用各个顶点进行中转来不断各个更新各个顶点之间最小路径,直至各个顶点之间均为最短路径即可。

定义邻接矩阵及辅助数组

#include<stdbool.h>
#define MAXSIZE 100
#define INF 0x3f3f3f3f
//邻接矩阵
typedef struct
{
    char vexs[MAXSIZE];
    int arcs[MAXSIZE][MAXSIZE];
    int vexnum,arcnum;
}AMGraph;
int P[MAXSIZE][MAXSIZE];//最短路径上顶点的前一顶点的序号
int D[MAXSIZE][MAXSIZE];//记录顶点之间的最短路径长度

Floyd算法

void Floyd(AMGraph G)
{
    for(int i=0;i<G.vexnum;i++)
    {
        for(int j=0;j<G.vexnum;j++)
        {
            D[i][j]=G.arcs[i][j];
            if(D[i][j]<INF&&i!=j)
            {
                P[i][j]=i;
            }
            else
            {
                P[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(D[i][k]+D[k][j]<D[i][j])
                {
                    D[i][j]=D[i][k]+D[k][j];
                    P[i][j]=P[k][j];
                }
            }
        }
    }
    return ;
}

时间复杂度:O(n^3)

三、贝尔曼福特算法(Bellman-Ford)

Bellman-Ford: 解决负权单源最短路径,其本质是动态规划思想。*主要是对图进行最多V-1次松弛操作,得到源点到各点所有可能的最短路径,遍历都结束后,若再进行一次遍历,还能得到s到某些节点更短的路径的话,则说明存在负环路,所以还能够用来检测负环。BellmanFord支持解决负权路,没有负权也可以用,不过效率比Dijkstra低很多,所以更适合解决负权问题。

定义邻接矩阵及辅助数组

#include<stdbool.h>
#define MAXSIZE 100
#define INF 0x3f3f3f3f
//邻接矩阵
typedef struct
{
    char vexs[MAXSIZE];
    int arcs[MAXSIZE][MAXSIZE];
    int vexnum,arcnum;
}AMGraph;
int D[MAXSIZE];//记录当前最短路径长度
int P[MAXSIZE];//终点直接前驱顶点序号

Bellman-Ford算法

void BellmanFord(AMGraph G,int v)
{
    int n=G.vexnum;
    for(int i=0;i<n;i++)
    {
        D[i]=G.arcs[v][i];
        if(D[i]<INF)
        {
            P[i]=v;
        }
        else
        {
            P[i]=-1;
        }
    }
    D[v]=0;
    for(int i=2;i<G.vexnum-1;i++)
    {
        for(int j=0;j<G.vexnum;j++)
        {
            for(int k=0;k<G.vexnum;k++)
            {
                if((D[j]+G.arcs[j][k])<D[k])
                {
                    D[k]=D[j]+G.arcs[j][k];
                    P[k]=j;
                }
            }
        }
    }
    bool flag=true;
    for(int i=0;i<G.vexnum-1;i++)
    {
        for(int j=0;j<G.vexnum-1;j++)
        {
            if(D[i]+G.arcs[i][j]<D[j])
            {
                flag=false;
                break;
            }
        }
    }
    return flag;
}

时间复杂度:O(V*E) V(顶点数),E(边数)

DFS和BFS算法也可以求最短路径,但只能用于求无权图。

最短路线

利用最短路径的Path数组回溯出两点间最短路径的整条路线

邻接矩阵存储图:

void BeforePath(int a,int b)//参数a起点,参数b终点,根据最短路径终点前驱数组回溯路径上所有地点
{
	if (P[a][b] == -1)
	{
		return;
	}
	else if (P[a][b] == a)
	{
		printf("->");
		printf("%s", Site[b].name);
		return;
	}
	else
	{
		BeforePath(a, P[P[a][b]][b]);
		printf("->");
		printf("%s", Site[b].name);
		return;
	}
}

输出的路径未包括最初的起点,可以在函数外加上最初起点的输出

所有路径

利用DFS算法,借助辅助数组(或栈)输出两点间所有路径

邻接矩阵存储图:

void DFS(int a, int b,int A)//参数a为起点,参数b为终点,参数A为最初的起点,深度搜索寻找两点间所有路径
{
	for (int i = 1; i <= L; i++)
	{
		if (S[a][i] < INF && V[i] == 0)
		{
			if (i == b)
			{
				int j;
				printf("%s->", Site[A].name);
				for (j = 0; j < E; j++)
				{
					printf("%s->", Site[T[j]].name);
				}
				printf("%s\n\n",Site[b].name);
				F++;
			}
			else
			{
				V[i] = 1;
				T[E] = i;
				E++;
				DFS(i, b,A);
				V[i] = 0;
				E--;
			}
		}
	}
}

为了让路线更完整,多设置了一个参数A即最初的起点,递归时参数A不变,从而输出完整路径

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
网络自动生成最小路径的问题可以通过最短路径算法来解决。常见的最短路径算法有Dijkstra算法、Floyd算法、Bellman-Ford算法和SPFA算法。其中,Dijkstra算法适用于单源最短路径问题,即给定一个起点,求出起点到其他点的最短路径。Floyd算法适用于多源最短路径问题,即求出中任意两点之间的最短路径。Bellman-Ford算法和SPFA算法可以处理带有负权边的最短路径问题。 在使用这些算法时,需要根据具体的网络的特点选择合适的算法。例如,如果网络是有向且没有负权边,可以使用Dijkstra算法来求解最短路径。如果网络是有向且存在负权边,可以使用Bellman-Ford算法来求解最短路径。如果网络是无向,可以使用Floyd算法来求解最短路径。 需要注意的是,最小生成树和最短路径是不同的概念。最小生成树是指在连通中选择一些边,使得这些边构成一棵树,并且这棵树包含中的所有顶点,且边的权值和最小。而最短路径是指从一个指定的顶点出发,计算到其他所有顶点的最短路径。 因此,网络自动生成最小路径的问题可以通过最短路径算法来解决,具体选择哪种算法取决于网络的特点和需求。 #### 引用[.reference_title] - *1* *2* [【数据结构与算法】最小生成树 | 最短路径](https://blog.csdn.net/m0_63639164/article/details/128811968)[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^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [最小生成树、最短路径树](https://blog.csdn.net/Anne033/article/details/108703039)[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^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值