数据结构课设

(1)问题描述

设计一个校园导游程序,为来访的客人提供各种信息查询服务。

(2)设计要求

  1. 设计中北大学的校园平面图。以图中顶点表示校内各景点,存放景点名称、代号、简介等信息;以边表示路径,存放路径长度等相关信息。
  2. 为来访客人提供图中任意景点相关信息的查询。
  3. 为来访客人提供图中任意景点的问路查询,即查询任意两相景点之间的一条最短的简单路径。
  4. 求校园图的关节点。
  5. 为来访客人提供图中任意景点问路查询,即求任意两个景点之间的所有路径。
  6. 为来访客人提供校园图中多个景点的最佳访问路线查询,即求途经这多个景点的最佳路径。


(3)代码

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define INF 0x3f3f3f3f//无穷大
#define MAX 20//顶点最大值

typedef struct//顶点类型
{
    char name[20];
    int ID;
    char info[500];
} vertextype;
typedef int edgetype;//边权值类型
typedef struct
{
    vertextype vexs[MAX];
    edgetype edges[MAX][MAX];//邻接矩阵图类型
    int n, e;
} graph;
typedef int dist[MAX][MAX];   /* 距离向量类型*/
typedef int path[MAX][MAX];   /* 路径类型*/
graph g;
void plan()
{
    printf("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");
    printf("┃                                   ***中北大学校园平面图***                                 ┃\n");
    printf("┃                                                                                            ┃\n");
    printf("┃                                ╭─────╮    ╭─────╮                            ┃\n");
    printf("┃                  ╔══════│中北医院⑴│══│文体中心⑵│═╗                        ┃\n");
    printf("┃                  ║            ╰─────╯    ╰─────╯  ║                        ┃\n");
    printf("┃                  ║                                              ║                        ┃\n");
    printf("┃    ╭─────╮║    ╭────╮      ╭────╮        ╭───╮        ╭────╮┃\n");
    printf("┃    │龙山公园⑶│╬══│科艺苑⑷│═══│图书馆⑸│════│主楼⑹│════│体育场⑺│┃\n");
    printf("┃    ╰─────╯║    ╰────╯      ╰────╯        ╰───╯        ╰────╯┃\n");
    printf("┃                  ║                                             ║                 ║      ┃\n");
    printf("┃                  ║                                      ╭─────╮      ╭─────╮┃\n");
    printf("┃                  ║                                      │行知广场⑻│      │科技园区⑼│┃\n");
    printf("┃                  ║                                      ╰─────╯      ╰─────╯┃\n");
    printf("┃                  ║                                                                ║      ┃\n");
    printf("┃      ╭────╮║              ╭────╮      ╭───────╮              ║      ┃\n");
    printf("┃      │柏林园⑽│╬═══════│足球场⑾│═══│学术交流中心⑿│═══════╝      ┃\n");
    printf("┃      ╰────╯║              ╰────╯      ╰───────╯                      ┃\n");
    printf("┃                  ║                                                                        ┃\n");
    printf("┃             ╭────╮                                                                   ┃\n");
    printf("┃             │德怀楼⒀│                                                                   ┃\n");
    printf("┃             ╰────╯                                                                   ┃\n");
    printf("┃                  ║                                                                        ┃\n");
    printf("┃              ╭───╮                                                                    ┃\n");
    printf("┃              │正门⒁│                                                                    ┃\n");
    printf("┃              ╰───╯                                                                    ┃\n");
    printf("┃                                                                                            ┃\n");
    printf("┃                                   注:括号中数字代表景点序号                                ┃\n");
    printf("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n");
}
void mean()
{
    printf("\t\t\t\t┏━━━━━━━━━━━━━━━━━━━┓\n");
    printf("\t\t\t\t┃             **请选择功能**           ┃\n");
    printf("\t\t\t\t┃      1.查询景点信息                  ┃\n");
    printf("\t\t\t\t┃      2.查询推荐路线                  ┃\n");
    printf("\t\t\t\t┃      3.查询校园图关节点              ┃\n");
    printf("\t\t\t\t┃      4.退出                          ┃\n");
    printf("\t\t\t\t┗━━━━━━━━━━━━━━━━━━━┛\n");
}
void sub_mean()
{
    printf("\t\t\t\t┏━━━━━━━━━━━━━━━━━━━┓\n");
    printf("\t\t\t\t┃             **请选择功能**           ┃\n");
    printf("\t\t\t\t┃     1.查询两景点的最佳路径           ┃\n");
    printf("\t\t\t\t┃     2.查询两景点之间所有路径         ┃\n");
    printf("\t\t\t\t┃     3.查询途径多个景点的最佳访问路线 ┃\n");
    printf("\t\t\t\t┃     4.退出                           ┃\n");
    printf("\t\t\t\t┗━━━━━━━━━━━━━━━━━━━┛\n");
    //*printf("请选择功能:");
}
/*函数功能:建立图的邻接矩阵存储结构*/
void creat_graph(char *s, int c)
{
    int i, j, k, w;
    FILE *rf;
    rf = fopen(s, "r");
    if (rf)
    {
        fscanf(rf, "%d%d", &g.n, &g.e);
        for (i = 1; i<=g.n; i++)
        {
            fscanf(rf, "%d%s ", &g.vexs[i].ID, g.vexs[i].name);
            fgets(g.vexs[i].info, 500, rf);
        }
        for (i = 1; i<=g.n; i++)
            for (j = 1; j<=g.n; j++)
                if (i == j) g.edges[i][j] = 0;
                else g.edges[i][j] = INF;
        for (k = 0; k<g.e; k++)
        {
            fscanf(rf, "%d%d%d", &i, &j, &w);
            g.edges[i][j] = w;
            if (c == 0) g.edges[j][i] = w;   /*如果c==0则建立无向图邻接矩阵,否则建立有向图邻矩阵*/
        }
        fclose(rf);
    }
    else g.n = 0;
}


/*函数功能:Floyd方法求所有顶点对间的最短路径*/
void floyd(path p, dist d)
{
    int i, j, k;
    for (i = 1; i<=g.n; i++)
        for (j = 1; j<=g.n; j++)
        {
            d[i][j] = g.edges[i][j];
            p[i][j]=j;
        }
    for (k = 1; k<=g.n; k++) /*递推求解每一对顶点间的最短距离*/
    {
        for (i = 1; i<=g.n; i++)
            for (j = 1; j<=g.n; j++)
                if (d[i][j]>(d[i][k] + d[k][j]))
                {
                    d[i][j] = d[i][k] + d[k][j];
                    p[i][j] = p[i][k];
                }
    }
}
/*函数功能输出最短路径*/
void put_short(int sta, int end,path p, dist d)
{
    printf("\n最短距离为:\n");
    printf("%dM", d[sta][end]);
    printf("\n最佳路线为:\n");
    int tmp=sta;
    printf("(%d)%s",sta,g.vexs[sta].name);
    while(tmp!=end)
    {
        tmp=p[tmp][end];
        printf(" -> (%d)%s",tmp,g.vexs[tmp].name);
    }
    printf("\n");
}
int min(int a,int b)
{
    return a>b?b:a;
}
/*函数功能:求割点的dfs过程*/
void cut_dfs(int u,int *vis,int *dfn,int *par,int*low,int *cut)
{
    int v;
    static int dep=0;
    int child=0;
    vis[u]=1;
    dfn[u]=low[u]=++dep;
    for(v=1; v<=g.n; v++)
    {
        if(g.edges[u][v]!=INF&&g.edges[u][v])
        {
            if(!vis[v])
            {
                child++;
                par[v]=u;
                cut_dfs(v,vis,dfn,par,low,cut);
                low[u]=min(low[u],low[v]);
                if(par[u]==-1&&child>1)
                {
                    cut[u]=1;
                }
                else if(par[u]!=-1&&low[v]>=dfn[u])
                {
                    cut[u]=1;
                }
            }
            else if(v!=par[u])
            {
                low[u]=min(low[u],dfn[v]);
            }
        }
    }
}
/*函数功能:求割点*/
void cutver()
{
    int vis[MAX],dfn[MAX],par[MAX],low[MAX],cut[MAX];
    int i;
    int flag=0;
    for(i=1; i<=g.n; i++)
    {
        vis[i]=0;
        par[i]=-1;
        cut[i]=0;
    }
    for(i=1; i<=g.n; i++)
    {
        if(!vis[i])
        {
            cut_dfs(i,vis,dfn,par,low,cut);
            break;
        }
    }
    for(i=1; i<=g.n; i++)
        if(cut[i])
        {
            flag=1;
            break;
        }
    if(flag)
    {
        printf("校园图的关节点为:");
        for(i=1; i<=g.n; i++)
        {
            if(cut[i])
            {
                flag=1;
                printf(" (%d)%s",i,g.vexs[i].name);
            }
        }
        printf("\n");
    }
    else
    {
        printf("对不起,该校园图没有关节点!\n");
    }
}
/*函数功能:求两点间所有路径过程中求遍历过中的下一个点*/
int find_first(int cur,int vis_ver[],int vis_edg[][MAX])
{
    int i;
    for(i=1; i<=g.n; i++)
        if(!vis_ver[i]&&!vis_edg[cur][i]&&g.edges[cur][i]!=INF&&i!=cur)
            return i;
    return -1;
}
/*函数功能:求两点间的所有路径*/
void all_path(int sta,int end)
{
    int i;
    int vis_ver[MAX],vis_edg[MAX][MAX];
    int stack[MAX],top=-1;
    memset(vis_ver,0,sizeof(vis_ver));
    memset(vis_edg,0,sizeof(vis_edg));
    vis_ver[sta]=1;
    stack[++top]=sta;
    while(top>=0)
    {
        int em=stack[top];
        if(em==end)
        {
            for(i=0; i<top; i++)
                printf("(%d)%s -> ",stack[i],g.vexs[stack[i]].name);
            printf("(%d)%s\n",stack[top],g.vexs[stack[top]].name);
            printf("\n");
            vis_ver[em]=0;
            top--;
        }
        else
        {
            int cur=find_first(em,vis_ver,vis_edg);
            if(cur>=0)
            {
                stack[++top]=cur;
                vis_ver[cur]=1;
                vis_edg[em][cur]=1;
            }
            else if(cur==-1)
            {
                vis_ver[em]=0;
                for(i=1; i<=g.n; i++)
                    vis_edg[em][i]=0;
                top--;
            }
        }
    }
}
/*函数功能:求途径多个点的最佳路径的辅助输出函数*/
void shiftput(int sta, int end,path p, dist d)
{
    int tmp=sta;
    while(tmp!=end)
    {
        tmp=p[tmp][end];
        printf(" -> (%d)%s",tmp,g.vexs[tmp].name);
    }
}
/*函数功能:求途径多个点的最佳路径*/
void road_path(int staver,int *path_ver,int vercou,path p,dist d)
{
    int i,vis[MAX];
    memset(vis,0,sizeof(vis));
    for(i=0; i<vercou; i++)
        vis[path_ver[i]]=2;//表示要经过的点
    vis[staver]=1;
    int cur=staver;
    int flag=1;
    printf("(%d)%s",staver,g.vexs[staver].name);
    while(1)
    {
        flag=0;
        int mindis=INF,minver=-1;
        for(i=1; i<=g.n; i++)
        {
            if(vis[i]==2)
            {
                flag=1;
                if(d[cur][i]<mindis)
                {
                    mindis=d[cur][i];
                    minver=i;
                }
            }
        }
        if(flag==0) break;
        shiftput(cur,minver,p,d);
        vis[minver]=1;
        cur=minver;
    }
    printf("\n");
}
int main()
{
    creat_graph("graph.txt", 0);
    plan();
    mean();
    int cho,sub_cho;
    while(scanf("%d",&cho))
    {
        getchar();
        int i;
        int staver, endver;
        int vernum,vercou;
        char yorn;
        dist d;
        path p;
        int path_ver[MAX];
        switch(cho)
        {
        case 1:
            yorn='y';
            while(1)
            {
                if(yorn=='n')
                {
                    system("cls");
                    plan();
                    mean();
                    break;
                }
                else if(yorn=='y')
                {
                    system("cls");
                    plan();
                    printf("请输入景点序号:");
                    scanf("%d", &vernum);
                    getchar();
                    puts(g.vexs[vernum].info);
                }
                else
                {
                    printf("输入错误!\n");
                }
                printf("是否继续查询景点信息?y/n ");
                scanf("%c",&yorn);
                getchar();
            }
            break;
        case 2:
            yorn='y';
            while(1)
            {
                if(yorn=='n')
                {
                    out:system("cls");
                    plan();
                    mean();
                    break;
                }
                else if(yorn=='y')
                {
                    system("cls");
                    plan();
                    sub_mean();
                    scanf("%d",&sub_cho);
                    getchar();
                    switch(sub_cho)
                    {
                    case 1:
                        floyd(p,d);
                        yorn='y';
                        while(1)
                        {
                            if(yorn=='n')
                            {
                                system("cls");
                                plan();
                                sub_mean();
                                break;
                            }
                            else if(yorn=='y')
                            {
                                system("cls");
                                plan();
                                printf("请输入起点序号:");
                                scanf("%d",&staver);
                                getchar();
                                printf("请输入终点序号:");
                                scanf("%d",&endver);
                                getchar();
                                put_short(staver,endver,p,d);
                            }
                            else
                            {
                                printf("输入错误!");
                            }
                            printf("是否继续查询两点之间最短路径?y/n ");
                            scanf("%c",&yorn);
                            getchar();
                        }
                        break;
                    case 2:
                        yorn='y';
                        while(1)
                        {
                            if(yorn=='n')
                            {
                                system("cls");
                                plan();
                                sub_mean();
                                break;
                            }
                            else if(yorn=='y')
                            {
                                system("cls");
                                plan();
                                printf("请输入起点序号:");
                                scanf("%d",&staver);
                                getchar();
                                printf("请输入终点序号:");
                                scanf("%d",&endver);
                                getchar();
                                all_path(staver,endver);
                            }
                            else
                            {
                                printf("输入错误!");
                            }
                            printf("是否继续查询两点之间所有路径?y/n ");
                            scanf("%c",&yorn);
                            getchar();
                        }
                        break;
                    case 3:
                        floyd(p,d);
                        yorn='y';
                        while(1)
                        {
                            if(yorn=='n')
                            {
                                system("cls");
                                plan();
                                sub_mean();
                                break;
                            }
                            else if(yorn=='y')
                            {
                                system("cls");
                                plan();
                                printf("请输入起点序号:");
                                scanf("%d",&staver);
                                getchar();
                                printf("请输入要经过的景点数目:");
                                scanf("%d",&vercou);
                                getchar();
                                printf("依次输入要经过的景点序号:\n");
                                for(i=0; i<vercou; i++)
                                {
                                    scanf("%d",&path_ver[i]);
                                    getchar();
                                }
                                road_path(staver,path_ver,vercou,p,d);
                            }
                            else
                            {
                                printf("输入错误!");
                            }
                            printf("是否继续查询途径多个景点的最佳路径?y/n ");
                            scanf("%c",&yorn);
                            getchar();
                        }
                        break;
                    case 4:
                        goto out;
                        break;
                    default:
                        printf("输入错误!");
                    }
                }
                printf("是否继续查询推荐路线?y/n ");
                scanf("%c",&yorn);
                getchar();
            }
            break;
        case 3:
            cutver();
            printf("按任意键返回主菜单...");
            getchar();
            system("cls");
            plan();
            mean();
            break;
        case 4:
            return 0;
        default:
            printf("输入错误!");
        }
    }
    return 0;
}


  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值