算法设计与分析实验三:贪心法求解单源最短路径问题


【实验内容】
(1)单源最短路径问题,并对算法进行时间复杂性分析。
【编译环境】devc++ 5.11
【解题思路】
1.输入图的结点个数和代价矩阵

2.借鉴课本"算法设计与分析第二版"146页习题7第四点提到的Dijkstra算法,相关博客很多可以看看原理…

3.求解单源最短路径问题

4.对于复杂性
【参考内容】
迪杰斯特拉算法实现原理
【代码分析】

图的节点个数和代价矩阵

头文件和宏定义

#include<stdio.h>
#include<random>
#include<time.h>

#define V 4                   //顶点的最大个数
#define INFINITY 65535

存储代价矩阵的结构体

struct MGraph
{
	int vexnum;
	int arcs[V][V];
};

输入代价矩阵并调用算法

	srand(time(NULL));
	MGraph G;
	G.vexnum = V;
	for(int i=0;i<V;i++)
	{
		for(int j=0;j<V;j++)
		{
			if(i==j)
			{
				G.arcs [i][j] = INFINITY;
			} 
			else
				G.arcs [i][j] = rand()%INFINITY+1;
		}
	}
	//输入完毕后调用算法 
	//第二个参数为出发原点,可以改成别的。 
	Dijkstra_minTree(G, 0);

迪杰斯特拉算法实现

//迪杰斯特拉算法,v0表示有向网中起始点所在数组中的下标
void Dijkstra_minTree(MGraph G, int v0) //G是一个存储矩阵信息的结构体
{
    int final[V];//为各个顶点配置一个标记值,用于确认该顶点是否已经找到最短路径相当于一个flag位。 
    //对各数组进行初始化
    int p[V];
	int D[V];
    for (int v = 0; v < G.vexnum; v++) {
        final[v] = 0;//最开始都是0,未进入最短路径 
        D[v] = G.arcs[v0][v];//记录V0到其他定点的直接路径长度。 
        p[v] = 0; 
    }
    //由于以v0位下标的顶点为起始点,所以不用再判断
    D[v0] = 0;
    final[v0] = 1;//最开始在最短路径里,只能确定0和自己相连。
    int k = 0;
    for (int i = 0; i < G.vexnum; i++) {//循环vexnum次即最大点数。 
        int min = INFINITY;
        //选择到各顶点权值最小的顶点,即为本次能确定最短路径的顶点
        for (int w = 0; w < G.vexnum; w++) {
            if (!final[w]) {//w点没在最短路径中
                if (D[w] < min) {
                    k = w;
                    min = D[w];
                }
            }
        }
        //设置该顶点的标志位为1,避免下次重复判断
        final[k] = 1;
        //对v0到各顶点的权值进行更新,以新加入的k结点为起点更新距离,并且在p[]中标记前驱 
        for (int w = 0; w < G.vexnum; w++) {
            if (!final[w] && (min + G.arcs[k][w] < D[w])) {
                D[w] = min + G.arcs[k][w];
                p[w] = k;//记录各个最短路径上存在的顶点。 
            }
        }
    }
    printf("权值矩阵:\n");
    for(int i=0;i<V;i++)
    {
    	for(int j=0;j<V;j++)
    	{
    		printf("%-8d",G.arcs [i][j]);
		}
		printf("\n");
	}
	for(int i=0;i<V;i++)
    {
    	printf("%d->%d最短路径:%-8d\n",v0,i,D[i]);
	}
}

输出

贪心法求解单源最短路径问题输出

复杂度分析

贪心法求解单源最短路径问题复杂度分析

源代码

#include<stdio.h>
#include<random>
#include<time.h>

#define V 4                   //顶点的最大个数
#define INFINITY 65535

struct MGraph
{
	int vexnum;
	int arcs[V][V];
};

//迪杰斯特拉算法,v0表示有向网中起始点所在数组中的下标
void Dijkstra_minTree(MGraph G, int v0) //G是一个存储矩阵信息的结构体
{
    int final[V];//为各个顶点配置一个标记值,用于确认该顶点是否已经找到最短路径相当于一个flag位。 
    //对各数组进行初始化
    int p[V];
	int D[V];
    for (int v = 0; v < G.vexnum; v++) {
        final[v] = 0;//最开始都是0,未进入最短路径 
        D[v] = G.arcs[v0][v];//记录V0到其他定点的直接路径长度。 
        p[v] = 0; 
    }
    //由于以v0位下标的顶点为起始点,所以不用再判断
    D[v0] = 0;
    final[v0] = 1;//最开始在最短路径里,只能确定0和自己相连。
    int k = 0;
    for (int i = 0; i < G.vexnum; i++) {//循环vexnum次即最大点数。 
        int min = INFINITY;
        //选择到各顶点权值最小的顶点,即为本次能确定最短路径的顶点
        for (int w = 0; w < G.vexnum; w++) {
            if (!final[w]) {//w点没在最短路径中
                if (D[w] < min) {
                    k = w;
                    min = D[w];
                }
            }
        }
        //设置该顶点的标志位为1,避免下次重复判断
        final[k] = 1;
        //对v0到各顶点的权值进行更新,以新加入的k结点为起点更新距离,并且在p[]中标记前驱 
        for (int w = 0; w < G.vexnum; w++) {
            if (!final[w] && (min + G.arcs[k][w] < D[w])) {
                D[w] = min + G.arcs[k][w];
                p[w] = k;//记录各个最短路径上存在的顶点。 
            }
        }
    }
    printf("权值矩阵:\n");
    for(int i=0;i<V;i++)
    {
    	for(int j=0;j<V;j++)
    	{
    		printf("%-8d",G.arcs [i][j]);
		}
		printf("\n");
	}
	for(int i=0;i<V;i++)
    {
    	printf("%d->%d最短路径:%-8d\n",v0,i,D[i]);
	}
}

int main()
{
	srand(time(NULL));
	MGraph G;
	G.vexnum = V;
	for(int i=0;i<V;i++)
	{
		for(int j=0;j<V;j++)
		{
			if(i==j)
			{
				G.arcs [i][j] = INFINITY;
			} 
			else
				G.arcs [i][j] = rand()%INFINITY+1;
		}
	}
	//输入完毕后调用算法 
	//第二个参数为出发原点,可以改成别的。 
	Dijkstra_minTree(G, 0);
	return 0;
}
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值