数据结构实验三

哈尔滨工业大学计算学部

实验报告

课程名称:数据结构与算法

实验项目:图形结构及其应用

实验题目:最短路径算法

  • 实验目的

最短路径问题研究的主要有:单源最短路径问题和所有顶点对之间的最短路径问题。在计算机领域和实际工程中具有广泛的应用,如集成电路设计、GPS/ 游戏地图导航、智能交通、路由选择、铺设管线等。本实验要求设计和实现 Dijkstra 算法和 Floyd-Warshall 算法,求解最短路径问题

二、实验要求及实验环境

实验要求:

1 实现单源最短路径的 Dijkstra 算法,输出源点及其到其他顶点的最短路径长度和最短路径。

2. 实现全局最短路径的 Floyd-Warshall算法。计算任意两个顶点间的最短距离矩阵和最短路径矩阵,并输出任意两个顶点间的最短路径长度和最短路径。

3. 利用 Dijkstra Floyd-Warshall 算法解决单目标最短路径问题:找出图中每个顶点 v 到某个指定顶点 c 最短路径。

4. 利用 Dijkstra Floyd-Warshall算法解决单顶点对间最短路径问题:对于某对顶点 v 和 u,找出 u 到 v 和 v 到 u 的一条最短路径。

5. 以文件形式输入图的顶点和边,并以适当的方式展示相应的结果。要求顶点

不少于 10 个,边不少于 13 个。

实验环境:

我本次使用Visual Studio Code来编写C++程序。

三、设计思想(本程序中的用到的所有数据类型的定义,主程序的流程图及各程序模块之间的调用关系、核心算法的主要步骤)

1.所使用的数据结构:

(1)定义了MTGraph结构体来存储图结构,其成员有vertex一维数组用于存储图的顶点序列,edge二维数组用于存储边的权值,n用于存储顶点数,e用于存储边数。

(2)D一维数组,用于存储源点到各个顶点的最短路径长度

(3)S一维数组,用于存储顶点是否已经求出最短路径

(4)P一维数组,用于存储最短路径的前一个结点

(5)Length二维数组,用于存储任意两个顶点间的最短路径

(6)Road二维数组,用于最短路径编号

  1. 算法设计逻辑及程序运行效果:

(1)int MinCost(MTGraph *G)

该函数用于计算当前最短路径下标,temp为所有未确定最短路径中最短的路径,初始化temp为min即两个顶点之间没有边,可认为为无穷大,初始化w为1,循环除源点外的各个顶点,如果该顶点未确定最短路径,且其当前最短路径值小于temp,则更新temp为当前最短路径值,循环结束后,得到temp为最短路径,w为最短路径下标。

2void CreateMGraph(MTGraph *G)

该函数用于从文件中读取创建图,下面为文件输入信息,依据输入格式读取顶点数,边数,顶点序列及边的权值即可。

10 18

0 1 2 3 4 5 6 7 8 9

0 1 4

1 8 3

8 9 2

1 7 3

2 5 9

2 7 5

3 4 4

3 9 10

4 7 15

4 6 12

5 1 7

5 3 9

5 8 12

6 8 4

6 2 1

7 3 2

8 9 14

7 6 14

3void ShowMTGraph(MTGraph *G)

该函数用于输出从文件中读入的数据,遍历存储顶点序列的vertex矩阵及存储边信息的edge信息矩阵即可。下面为控制台输出信息。

the dots list:

0123456789

the adjacency matrix:

99 4 99 99 99 99 99 99 99 99

99 99 99 99 99 99 99 3 3 99

99 99 99 99 99 9 99 5 99 99

99 99 99 99 4 99 99 99 99 10

99 99 99 99 99 99 12 15 99 99

99 7 99 9 99 99 99 99 12 99

99 99 1 99 99 99 99 99 4 99

99 99 99 2 99 99 14 99 99 99

99 99 99 99 99 99 14 99 99 14

99 99 99 99 99 99 14 99 99 99

4void Dijkstra(MTGraph *G)

该函数用于求源点0到每个顶点的最短路径,先初始化D,P,S矩阵,之后循环遍历除源点外的所有点,获取到所有未确定最短路径中最短路径的下标,再嵌套循环遍历除源点外的所有点,如果其最短路径未确定,则计算已确定的w的最短路径加上w与j之间边的长度,如果其小于原来的值,则更换,且找到j的最短路径。打印出如下输出。

0->1

distance:4

path:0->1

0->2

distance:22

path:0->1->7->6->2

0->3

distance:9

path:0->1->7->3

0->4

distance:13

path:0->1->7->3->4

0->5

distance:31

path:0->1->7->6->2->5

0->6

distance:21

path:0->1->7->6

0->7

distance:7

path:0->1->7

0->8

distance:7

path:0->1->8

0->9

distance:19

path:0->1->7->3->9

5void Floyd(MTGraph *G)

该函数用于通过Floyd算法求任意两个顶点之间的最短路径,先初始化Length及Road矩阵,之后通过三层循环确定最短路径长度及其前驱结点。并打印出如下输出。

最短距离矩阵

inf 4 22 9 13 31 21 7 7 19

inf 34 18 5 9 27 17 3 3 15

inf 16 20 7 11 9 19 5 19 17

inf 33 17 21 4 26 16 19 20 10

inf 29 13 17 21 22 12 15 16 27

inf 7 25 9 13 34 24 10 10 19

inf 17 1 8 12 10 18 6 4 18

inf 31 15 2 6 24 14 20 18 12

inf 31 15 22 26 24 14 20 18 14

inf 31 15 22 26 24 14 20 18 32

最短路径矩阵

-1 -1 7 7 7 7 7 1 1 7

-1 7 7 7 7 7 7 -1 -1 7

-1 5 7 7 7 -1 7 -1 5 7

-1 6 6 7 -1 6 4 4 6 -1

-1 6 6 7 7 6 -1 -1 6 7

-1 -1 7 -1 3 7 7 1 1 3

-1 5 -1 7 7 2 8 2 -1 7

-1 6 6 -1 3 6 -1 6 6 3

-1 6 6 7 7 6 -1 6 6 -1

-1 6 6 7 7 6 -1 6 6 7

路径及长度

0->0: no way

0->1: distance:4 path:0->1

0->2: distance:22 path:0->1->7->6->2

0->3: distance:9 path:0->1->7->3

0->4: distance:13 path:0->1->7->3->4

0->5: distance:31 path:0->1->7->6->2->5

0->6: distance:21 path:0->1->7->6

0->7: distance:7 path:0->1->7

0->8: distance:7 path:0->1->8

0->9: distance:19 path:0->1->7->3->9

1->0: no way

1->1: distance:34 path:1->7->6->2->5->1

1->2: distance:18 path:1->7->6->2

1->3: distance:5 path:1->7->3

1->4: distance:9 path:1->7->3->4

1->5: distance:27 path:1->7->6->2->5

1->6: distance:17 path:1->7->6

1->7: distance:3 path:1->7

1->8: distance:3 path:1->8

1->9: distance:15 path:1->7->3->9

2->0: no way

2->1: distance:16 path:2->5->1

2->2: distance:20 path:2->7->6->2

2->3: distance:7 path:2->7->3

2->4: distance:11 path:2->7->3->4

2->5: distance:9 path:2->5

2->6: distance:19 path:2->7->6

2->7: distance:5 path:2->7

2->8: distance:19 path:2->5->1->8

2->9: distance:17 path:2->7->3->9

3->0: no way

3->1: distance:33 path:3->4->6->2->5->1

3->2: distance:17 path:3->4->6->2

3->3: distance:21 path:3->4->7->3

3->4: distance:4 path:3->4

3->5: distance:26 path:3->4->6->2->5

3->6: distance:16 path:3->4->6

3->7: distance:19 path:3->4->7

3->8: distance:20 path:3->4->6->8

3->9: distance:10 path:3->9

4->0: no way

4->1: distance:29 path:4->6->2->5->1

4->2: distance:13 path:4->6->2

4->3: distance:17 path:4->7->3

4->4: distance:21 path:4->7->3->4

4->5: distance:22 path:4->6->2->5

4->6: distance:12 path:4->6

4->7: distance:15 path:4->7

4->8: distance:16 path:4->6->8

4->9: distance:27 path:4->7->3->9

5->0: no way

5->1: distance:7 path:5->1

5->2: distance:25 path:5->1->7->6->2

5->3: distance:9 path:5->3

5->4: distance:13 path:5->3->4

5->5: distance:34 path:5->1->7->6->2->5

5->6: distance:24 path:5->1->7->6

5->7: distance:10 path:5->1->7

5->8: distance:10 path:5->1->8

5->9: distance:19 path:5->3->9

6->0: no way

6->1: distance:17 path:6->2->5->1

6->2: distance:1 path:6->2

6->3: distance:8 path:6->2->7->3

6->4: distance:12 path:6->2->7->3->4

6->5: distance:10 path:6->2->5

6->6: distance:18 path:6->8->6

6->7: distance:6 path:6->2->7

6->8: distance:4 path:6->8

6->9: distance:18 path:6->2->7->3->9

7->0: no way

7->1: distance:31 path:7->6->2->5->1

7->2: distance:15 path:7->6->2

7->3: distance:2 path:7->3

7->4: distance:6 path:7->3->4

7->5: distance:24 path:7->6->2->5

7->6: distance:14 path:7->6

7->7: distance:20 path:7->6->2->7

7->8: distance:18 path:7->6->8

7->9: distance:12 path:7->3->9

8->0: no way

8->1: distance:31 path:8->6->2->5->1

8->2: distance:15 path:8->6->2

8->3: distance:22 path:8->6->2->7->3

8->4: distance:26 path:8->6->2->7->3->4

8->5: distance:24 path:8->6->2->5

8->6: distance:14 path:8->6

8->7: distance:20 path:8->6->2->7

8->8: distance:18 path:8->6->8

8->9: distance:14 path:8->9

9->0: no way

9->1: distance:31 path:9->6->2->5->1

9->2: distance:15 path:9->6->2

9->3: distance:22 path:9->6->2->7->3

9->4: distance:26 path:9->6->2->7->3->4

9->5: distance:24 path:9->6->2->5

9->6: distance:14 path:9->6

9->7: distance:20 path:9->6->2->7

9->8: distance:18 path:9->6->8

9->9: distance:32 path:9->6->2->7->3->9

(6)void Single_Target_Floyd(MTGraph *G, int v)

该函数用于求解单目标最短路径,利用前面写过的Folyd算法易求解此问题,调用Folyd算法后,只需按照需要输出即可。下面为输出结果。

0->4:   distance:13     path:0->1->7->3->4

1->4:   distance:9      path:1->7->3->4

2->4:   distance:11     path:2->7->3->4

3->4:   distance:4      path:3->4

4->4:   distance:21     path:4->7->3->4

5->4:   distance:13     path:5->3->4

6->4:   distance:12     path:6->2->7->3->4

7->4:   distance:6      path:7->3->4

8->4:   distance:26     path:8->6->2->7->3->4

9->4:   distance:26     path:9->6->2->7->3->4

(7)void Single_Source_Floyd(MTGraph *G, int u, int v)

该函数用于求单顶点对间最短路径,,利用前面写过的Floyd算法易求解此问题,调用Floyd算法后,只需按照需要输出即可。下面为输出结果。

3->6: distance:16 path:3->4->6

6->3: distance:8 path:6->2->7->3

四、测试结果

已在第三部分结合函数介绍给出运行结果。

五、经验体会与不足

通过此次实验的练习我更加熟悉栈的操作,并且发现了之前学习栈上的漏洞,并且由于程序代码较多,存在“牵一发而动全身”的情况,我认识到先有一个整体架构再填充细节的重要性,每修改一个地方都应注意是否会影响程序的其它部分,以下简述我在实验中遇到的问题。

  1. 对Dijkstra算法和Floyd算法的原理还有一些不清晰的地方,通过观看网课视频及老师讲解解决。
  2. 输出最短路径时没有初始化栈导致结果出错,与同学交流后发现该问题。

#include <iostream>

using namespace std;

#define MAX 20
const int MIN = 99;
int D[MAX];           //源点到顶点的当前最短距离
int P[MAX];           //源点到顶点的当前最短路径最后经过的顶点
bool S[MAX];          //判断顶点是否求出最短路径
int Length[MAX][MAX]; //最短路径长度
int Road[MAX][MAX];   //最短路径编号
typedef int VertexData;
typedef int EdgeData;

typedef struct
{
    VertexData vertex[MAX];  //顶点表
    EdgeData edge[MAX][MAX]; //邻接矩阵
    int n, e;                //图的顶点数和边数
} MTGraph;                   //邻接矩阵结构体

void Dijkstra(MTGraph *G); //源点0到其他顶点的最短路径
int MinCost(MTGraph *G);   //计算当前最短路径的下标
void CreateMGraph(MTGraph *G);
void ShowMTGraph(MTGraph *G);
void Floyd(MTGraph *G);
void Path(FILE *fp, int i, int j);
void Single_Target_Floyd(MTGraph *G, int v);        //单目标最短路径
void Single_Source_Floyd(MTGraph *G, int u, int v); //单顶点对最短路径
int main()
{
    MTGraph G;
    CreateMGraph(&G);
    ShowMTGraph(&G);
    Dijkstra(&G);
    Floyd(&G);
    Single_Target_Floyd(&G, 4);
    Single_Source_Floyd(&G, 3, 6);
    return 0;
}

void Dijkstra(MTGraph *G)
{
    int w;
    for (int i = 0; i < G->n; i++)
    {
        D[i] = G->edge[0][i];
        S[i] = false;
    }
    S[0] = true;
    // n-1次
    for (int i = 1; i < G->n; i++)
    {
        w = MinCost(G);
        S[w] = true;
        for (int v = 1; v < G->n; v++)
        {
            if ((S[v] != true) && ((D[w] + G->edge[w][v]) < D[v]))
            {
                D[v] = D[w] + G->edge[w][v];
                P[v] = w;
            }
        }
    }
    FILE *fp;
    fp = fopen("Dijkstra.txt", "w");
    //最短路径长度和最短路径
    for (int i = 1; i < G->n; i++)
    {
        if (D[i] != MIN)
        {
            fprintf(fp, "0->%d\ndistance:%d\npath:0", i, D[i]);
            int stack[MAX];
            int top = 0;
            stack[top] = i;
            while (stack[top] != 0)
            {
                int temp = stack[top];
                stack[++top] = P[temp];
            }
            top--;
            while (top >= 0)
                fprintf(fp, "->%d", stack[top--]);
            fprintf(fp, "\n\n");
        }
        else
            fprintf(fp, "0->%d:no way\n", i);
    }
    fclose(fp);
}

int MinCost(MTGraph *G)
{
    int w = 1;
    int temp = MIN;
    for (int i = 1; i < G->n; i++)
    {
        if (S[i] != true && D[i] < temp)
        {
            temp = D[i];
            w = i;
        }
    }
    return w;
}

void CreateMGraph(MTGraph *G)
{
    int i, j, w;
    FILE *fp;
    fp = fopen("input.txt", "r");
    if (fp == NULL)
    {
        printf("error:can't open the file");
        exit(0);
    }
    fscanf(fp, "%d %d", &G->n, &G->e);
    for (int i = 0; i < G->n; i++)
        for (int j = 0; j < G->n; j++)
            G->edge[i][j] = MIN;
    for (int i = 0; i < G->n; i++)
        fscanf(fp, "%d", &G->vertex[i]);
    for (int i = 0; i < G->e; i++)
    {
        fscanf(fp, "%d %d %d", &i, &j, &w);
        G->edge[i][j] = w;
    }
    fclose(fp);
}

void ShowMTGraph(MTGraph *G)
{
    cout << "the dots list:\n";
    for (int i = 0; i < G->n; i++)
        cout << G->vertex[i];
    cout << endl
         << "the adjacency matrix:" << endl;
    for (int i = 0; i < G->n; i++)
    {
        for (int j = 0; j < G->n; j++)
            cout << G->edge[i][j] << ' ';
        cout << endl;
    }
}

void Floyd(MTGraph *G)
{
    for (int i = 0; i < G->n; i++)
        for (int j = 0; j < G->n; j++)
        {
            Length[i][j] = G->edge[i][j];
            Road[i][j] = -1;
        }
    for (int k = 0; k < G->n; k++)
        for (int i = 0; i < G->n; i++)
            for (int j = 0; j < G->n; j++)
            {
                if (Length[i][j] > Length[i][k] + Length[k][j])
                {
                    Length[i][j] = Length[i][k] + Length[k][j];
                    Road[i][j] = k;
                }
            }

    FILE *fp;
    fp = fopen("Floyd.txt", "w");
    fclose(fp);
    fp = fopen("Floyd.txt", "a");
    //最短距离矩阵
    fprintf(fp, "最短距离矩阵\n");
    for (int i = 0; i < G->n; i++)
    {
        for (int j = 0; j < G->n; j++)
        {
            if (Length[i][j] != MIN)
                fprintf(fp, "%d\t", Length[i][j]);
            else
                fprintf(fp, "inf\t");
        }
        fprintf(fp, "\n");
    }
    fprintf(fp, "\n");

    //最短路径矩阵
    fprintf(fp, "最短路径矩阵\n");
    for (int i = 0; i < G->n; i++)
    {
        for (int j = 0; j < G->n; j++)
        {
            fprintf(fp, "%d\t", Road[i][j]);
        }
        fprintf(fp, "\n");
    }
    fprintf(fp, "\n");

    //路径及长度
    fprintf(fp, "路径及长度\n");
    for (int i = 0; i < G->n; i++)
    {
        for (int j = 0; j < G->n; j++)
        {
            fprintf(fp, "%d->%d:\t", i, j);
            if (Length[i][j] != MIN)
            {
                fprintf(fp, "distance:%d\t\tpath:", Length[i][j]);
                fprintf(fp, "%d", i);
                Path(fp, i, j);
                fprintf(fp, "->%d\n", j);
            }
            else
            {
                fprintf(fp, "no way\n");
            }
        }
        fprintf(fp, "\n");
    }
    fclose(fp);
}

void Path(FILE *fp, int i, int j)
{
    int k = Road[i][j];
    if (k != -1)
    {
        Path(fp, i, k);
        fprintf(fp, "->%d", k);
        Path(fp, k, j);
    }
}

void Single_Target_Floyd(MTGraph *G, int v)
{
    FILE *fp = fopen("Single_Target.txt", "w");
    for (int i = 0; i < G->n; i++)
    {
        fprintf(fp, "%d->%d:\t", i, v);
        if (Length[i][v] != MIN)
        {
            fprintf(fp, "distance:%d\t\tpath:", Length[i][v]);
            fprintf(fp, "%d", i);
            Path(fp, i, v);
            fprintf(fp, "->%d\n", v);
        }
        else
        {
            fprintf(fp, "no way\n");
        }
    }
    fclose(fp);
}

void Single_Source_Floyd(MTGraph *G, int u, int v)
{
    FILE *fp = fopen("Single_Source.txt", "w");

    fprintf(fp, "%d->%d:\t", u, v);
    if (Length[u][v] != MIN)
    {
        fprintf(fp, "distance:%d\t\tpath:", Length[u][v]);
        fprintf(fp, "%d", u);
        Path(fp, u, v);
        fprintf(fp, "->%d\n", v);
    }
    else
    {
        fprintf(fp, "no way\n");
    }

    fprintf(fp, "%d->%d:\t", v, u);
    if (Length[v][u] != MIN)
    {
        fprintf(fp, "distance:%d\t\tpath:", Length[v][u]);
        fprintf(fp, "%d", v);
        Path(fp, v, u);
        fprintf(fp, "->%d\n", u);
    }
    else
    {
        fprintf(fp, "no way\n");
    }
}

  • 25
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值