【实验内容】
(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;
}