数据结构大作业

地铁搭乘方案选择

分析思路

首先我们从网上找到成都的地铁路线图


将其中西南石油大学到世纪城的子图拿出来,进行筛选和删除,去掉一些正在修建的地铁线,精选得到了一份新的无向子图

假设不要求地铁乘坐的费用,不计算乘换地铁线和等待地铁的时间,我们可以用迪杰斯特拉算法的思想进行选择路线。
我们首先将地铁线上的站点进行编号,以西南石油大学为1号,依次编号;
接着从西南石油大学出发,每到一次站点就进行遍历比较,看接下来走哪个站点的路径比较短,走完整个地铁路线图并记录站点的编号,我们就得到了一个二叉树,从这个二叉树中找到我们需要的站点编号,以此从1号遍历到这个站点编号,就可以得到最短的路径以及路径图。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vJE56R2N-1593762301470)({PTA_URL}/api/private-image?p=user-uploads/1180335031380103168/2020-7-3/1593750163-e74b4918-c125-4972-be45-0ebb26542869.jpg)]
经过以上思路分析和查找,我们可以找到最短路径为:西南石油->驷马桥->火车北站->人民北路->骡马市->天府广场->市体育馆->倪家桥->火车南站->孵化园->世纪城,总路径为28,与百度地图上查到的3号线转7号线的最短路径是一致的,接下来我们用代码实现求最短路径。

算法实现

以下是我用迪杰斯特拉算法进行计算路线的代码:

#include
#include
#define max 10000000 
int a[1000][1000];
int d[1000];//d表示源节点到该节点的最小距离
int p[1000];//p标记访问过的节点
typedef struct leaves
{
    int number;
    struct leaves* last;
};
struct leaves tree[1000];
int i, j, k;
int m;//m代表边数
int n;//n代表点数
int main()
{
    printf("输入点的个数和边的个数\n");
    scanf("%d%d", &n, &m);
    int    min1;
    int    x, y, z;
    printf("请键入每个边相邻的点序号以及边的权值:\n");
    for (i = 1; i <= m; i++)
    {
        scanf("%d%d%d", &x, &y, &z);
        a[x][y] = z;
        a[y][x] = z;
    }
    for (i = 1; i <= n; i++)
    {
        d[i] = max;
        tree[i].last = NULL;
        tree[i].number = i;

    }
    tree[1].last = &tree[0];
    d[1] = 0;
    for (i = 1; i <= n; i++)
    {
        min1 = max;
        //下面这个for找到未访问节点中d[j]值最小的那个节点作为下一个访问节点,用k标记
        for (j = 1; j <= n; j++)
            if (!p[j] && d[j] < min1)
            {
                min1 = d[j];
                k = j;
            }
        p[k] = 1; //访问标记

        for (j = 1; j <= n; j++)
        {
            if (a[k][j] != 0 && !p[j] && d[j] > d[k] + a[k][j])
            {
                d[j] = d[k] + a[k][j];
                tree[j].last = &tree[k];
            }
        }
    }
    int target;
    printf("输入目标的编号:");
    scanf("%d", &target);
    for (i = 1; i <= n; i++)
    {
        if (i == target)
        {
            printf("从源点到%d号所需要的最短路径为%d\n", target, d[i]);
            printf("路径为:");
            struct leaves* p;
            p = &tree[target];
            int path[1000];
            int path_i=0;
            while (p->last)
            {
                path[path_i] = p->number;
                p = p->last;
                path_i++;
            }

            for (path_i--; path_i>0; path_i--)
                printf("%d->", path[path_i]);
            printf("%d", path[path_i]);
        }
    }
    return 0;
}
/*
测试数据
36 55
1 2 12
2 3 1
2 8 2
2 7 4
3 9 1
3 4 1
4 5 2
4 10 1
5 6 3
6 13 2
6 12 3
7 18 4
7 19 3
8 9 2
8 17 3
9 10 1
9 11 2
10 12 3
11 14 2
11 15 1
12 20 3
12 15 3
13 23 4
14 16 1
14 17 1
15 16 1
15 21 3
17 22 1
18 26 1
19 27 2
20 23 2
20 24 2
21 25 1
22 28 3
22 26 2
23 29 1
24 29 1
24 30 1
24 25 3
25 31 2
25 28 3
26 28 2
26 27 2
27 32 4
28 32 1
29 30 1
30 31 1
30 36 19
31 32 2
31 33 3
32 34 4
33 34 2
33 35 2
34 36 16
35 36 12
35

*/

下面是我们运行程序并输入数据后得到的结果,将分析出的站点与代码运行得到的结果对比发现完全一致,代码运行成功!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a4rbE6A2-1593762301472)({PTA_URL}/api/private-image?p=user-uploads/1180335031380103168/2020-7-3/1593750446-af57c06f-92d6-471a-b1a0-147317a9d924.png)]

算法性能:

由于我使用的迪杰斯特拉算法,所以计算出了西南石油大学到我们输入子图中所有站点的最短路线和最短路径,计算时间和占用空间较大,其中还使用了多次类冒泡排序的for循环,导致计算时间大大增加,但鉴于成都地铁线路站点和地铁线较少,对计算时间影响较小;
算法的时间复杂度:O(n)=n+n(2*n)+n+m=2n+n(2n)+m
算法的空间复杂度:使用邻接矩阵储存,占用空间n^2+m

你可能感兴趣的:(c,数据结构)