数据结构期末作业

//图--肇庆学院
//首先用结构体存储各个学校的建筑等
//再建立图---使用无向图----图存储路径长度
//目的:方便参观肇庆学院的最短路径 输入各个景点
//给输入 一个图:参观各个景点的最短路径【邻接矩阵】
//额外功能:平面图增加或删除景点或边(路径),修改边值
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
#pragma warning(disable:4996)
#define Maxnn 50
#define  INFINITY 3213123//未被赋值,当成无穷大
int visited[50];//用于标识顶点是否已经访问过
int Menu();//初始页面
typedef struct view
{
    int position;//景点编号
    char name[32];//景点名称
    char introduction[100];//景点介绍
}View;
typedef struct mgraph
{
    View vexs[Maxnn];//顶点
    int arcnum, vexnum;//边数与顶点数
    int arcs[Maxnn][Maxnn];//邻接矩阵
}mgraph;
mgraph campus;
int Menu();//主菜单
mgraph Init();//初始景点信息
void IntroductionCampus(mgraph g);//介绍肇庆学院景点
void dispath(int dist[], int path[], int s[], int n, int v, mgraph g);//输出Dijkstra
void FromBeginToSth_Dijkstra(mgraph g);//采用Dijkstra展现某一景点到各个景点的最短路径
void ppath(int path[][Maxnn], int a, int b, mgraph g);//
void dispath_floyd(int A[][Maxnn], int path[][Maxnn], int n, mgraph g);//输出floyd
void InquireAToB_shortest(mgraph g);//采用floyd来展现 某一景点到 另一景点的最短路径
void PrintfCampus(mgraph g);//输出邻接矩阵(存着各路径长)
int locatevex(mgraph g, int v);//根据景点编号获得景点的序列
int ChangeGraph(mgraph* g);//进入改变图的页面
int creatgraph(mgraph* g);//建立新图
int DeleteVex(mgraph* g);//删除顶点
int DeleteArc(mgraph* g);//删除边
int AddVex(mgraph* g);//增添顶点
int AddArc(mgraph* g);//增添边
int FixGraph(mgraph* g);//修改图
int main();//主函数

int Menu()
{
    int n;
    char c;
    printf("\n\n\t==============实验:肇庆学院一日游==============\n");
    printf("\n\t1.学校景点介绍");
    printf("\n\t2.查看到各个景点浏览路线");//采用        Dijkstra ,根据用户输入的起始景点编号,求出该景点到其他景点的最短路径线路以及距离
    printf("\n\t3.查询景点间最短路径");//采用   Floyd,输入起始景点以及目的地景点编号,查询任意两个景点之间的最短路径线路以及距离
    printf("\n\t4.更改景点的信息");
    printf("\n\t5.打印邻接矩阵");
    printf("\n\t0.退出");
    do
    {
        fflush(stdin);
        printf("\n\n\t请输入数字0-8选择功能:");
        c = getchar();
        n = c - 48;
        /*if (n < 0 || n>7)
            printf("\t\t\t输入选项错误!请重新输入选项");*/
    } while (n < 0 || n>5);
    return n;
}
mgraph Init()
{
    mgraph c;
    int i, j;
    i = j = 0;
    c.vexnum = 27;
    c.arcnum = 38;
    for (i = 0; i < c.vexnum; i++)
    {
        c.vexs[i].position = i;//依次给各个景点编号
    }
    strcpy(c.vexs[0].name, "办公大楼");
    strcpy(c.vexs[0].introduction, "进入肇庆学院正前方便可看到");
    strcpy(c.vexs[1].name, "中巴软件大楼");
    strcpy(c.vexs[1].introduction, "旧计算机学院");
    strcpy(c.vexs[2].name, "实训大楼");
    strcpy(c.vexs[2].introduction, "新计算机学院,1楼有羽毛球场");
    strcpy(c.vexs[3].name, "实验大楼");
    strcpy(c.vexs[3].introduction, "电子学院");
    strcpy(c.vexs[4].name, "体育馆");
    strcpy(c.vexs[4].introduction, "共3楼,一楼有乒乓球场,二楼有篮球场");
    strcpy(c.vexs[5].name, "游泳馆");
    strcpy(c.vexs[5].introduction, "夏天开放,一次10块,办卡8块");
    strcpy(c.vexs[6].name, "艺术楼");
    strcpy(c.vexs[6].introduction, "有一片大空地是滑板爱好者与轮滑爱好者的天堂");
    strcpy(c.vexs[7].name, "理工大楼");
    strcpy(c.vexs[7].introduction, "是环化与制药、生科学院的大楼");
    strcpy(c.vexs[8].name, "翰墨池");
    strcpy(c.vexs[8].introduction, "肇庆学院最出名之处,池中有天鹅");
    strcpy(c.vexs[9].name, "行知湖");
    strcpy(c.vexs[9].introduction, "有种宁静的氛围,是艺术生的天堂");
    strcpy(c.vexs[10].name, "第一运动场");
    strcpy(c.vexs[10].introduction, "各路运动爱好者集聚于此");
    strcpy(c.vexs[11].name, "第二运动场");
    strcpy(c.vexs[11].introduction, "院运会开展的地方,但平时比较少人关顾");
    strcpy(c.vexs[12].name, "第一饭堂");
    strcpy(c.vexs[12].introduction, "比较普通,但二楼是教师饭堂");
    strcpy(c.vexs[13].name, "第二饭堂");
    strcpy(c.vexs[13].introduction, "比较好吃,但同时价格也比较昂贵");
    strcpy(c.vexs[14].name, "第三饭堂");
    strcpy(c.vexs[14].introduction, "价格实惠,关顾人数偏多,三楼有着超市");
    strcpy(c.vexs[15].name, "第四饭堂");
    strcpy(c.vexs[15].introduction, "三楼比较豪华,内置大屏幕有比赛的时候可以观看");
    strcpy(c.vexs[16].name, "福慧图书馆");
    strcpy(c.vexs[16].introduction, "肇庆学院内比较大型的图书馆,氛围很好");
    strcpy(c.vexs[17].name, "严宽裕图书馆");
    strcpy(c.vexs[17].introduction, "相对福慧图书馆规模要小一些");
    strcpy(c.vexs[18].name, "紫荆苑");
    strcpy(c.vexs[18].introduction, "公主楼纯住女生,住宿费很便宜但配置也差些");
    strcpy(c.vexs[19].name, "榕华苑1");
    strcpy(c.vexs[19].introduction, "公主楼纯住女生,住宿费正常1300一个月");
    strcpy(c.vexs[20].name, "紫荆书院");
    strcpy(c.vexs[20].introduction, "很豪华6人间有电梯");
    strcpy(c.vexs[21].name, "榕华苑2");
    strcpy(c.vexs[21].introduction, "巨豪华4人间有电梯");
    strcpy(c.vexs[22].name, "博学书院");
    strcpy(c.vexs[22].introduction, "男女混住楼下有篮球场");
    strcpy(c.vexs[23].name, "力行书院");
    strcpy(c.vexs[23].introduction, "男女混住,靠近第二运动场");
    strcpy(c.vexs[24].name, "厚德书院");
    strcpy(c.vexs[24].introduction, "男女混住,出门便有篮球场靠近校门口");
    strcpy(c.vexs[25].name, "教师活动中心");
    strcpy(c.vexs[25].introduction, "里面可以玩桌球、乒乓球等");
    strcpy(c.vexs[26].name, "生物园");
    strcpy(c.vexs[26].introduction, "里面有许多植物和鱼");
    for (i = 0; i < c.vexnum; i++)
    {
        for (j = 0; j < c.vexnum; j++)
        {
            c.arcs[i][j] = INFINITY;//初始化
            if (i == j)
            {
                c.arcs[i][j] = 0;
            }
        }
    }
    c.arcs[0][2] = 50;        c.arcs[0][3] = 60;        c.arcs[1][4] = 90;
    c.arcs[2][3] = 60;        c.arcs[2][8] = 40;        c.arcs[3][4] = 60;
    c.arcs[3][6] = 40;        c.arcs[4][5] = 70;        c.arcs[4][9] = 70;        c.arcs[4][10] = 80;
    c.arcs[4][17] = 200;    c.arcs[5][7] = 70;        c.arcs[6][9] = 40; 
    c.arcs[7][18]= 190;        c.arcs[8][11] = 50;
    c.arcs[9][12] = 40;        c.arcs[10][18] = 70;    c.arcs[11][12] = 60;
    c.arcs[11][14] = 50;    c.arcs[11][15] = 50;    c.arcs[12][16] = 50;    c.arcs[13][14] = 40; 
    c.arcs[13][22] = 60;    c.arcs[14][15] = 50;    c.arcs[14][20] = 90;    c.arcs[15][16] = 60;
    c.arcs[15][21] = 40;    c.arcs[16][17] = 60;    c.arcs[17][18] = 80;    c.arcs[18][19] = 60;
    c.arcs[20][21] = 60;    c.arcs[20][24] = 80;    c.arcs[22][23] = 60;    c.arcs[22][25] = 80; 
    c.arcs[23][24] = 60;    c.arcs[24][26] = 100;    c.arcs[25][26] = 100;
    for (i = 0; i < c.vexnum; i++) {//因为对称,所以将其补充完毕
        for (j = 0; j < c.vexnum; j++)
            c.arcs[j][i] = c.arcs[i][j];
    }
    return c;

void IntroductionCampus(mgraph g)
{
    for (int i = 0; i < g.vexnum; i++)
    {
        printf("%d     %s        %s\n", g.vexs[i].position, g.vexs[i].name, g.vexs[i].introduction);
    }
}
void dispath(int dist[], int path[], int s[], int n, int v,mgraph g)
{
    int i, k,j;
    for (i = 0; i < n; i++)
    {
        if (s[i] == 1) {
            k = i;
            printf("v%d.%s 到 v%d.%s的最短路径为:",g.vexs[v].position, g.vexs[v].name, g.vexs[i].position, g.vexs[i].name);
            if (k == v)
            {
                printf("%d.%s", k, g.vexs[k].name);
            }
            while (k != v)
            {
                printf("v%d.%s<--", k,g.vexs[k].name);
                k = path[k];
            }
            printf("v%d.%s \n路径长度为:%d\n",g.vexs[v].position, g.vexs[v].name, dist[i]);
        }
    }
}
void FromBeginToSth_Dijkstra(mgraph g)
{
    int v;
    printf("请输入起始位置(编号):");
    scanf("%d", &v);
    while (v<0 || v>g.vexnum)
    {
        printf("您输入的编号不正确,请重新输入");
        return;
        scanf("%d", &v);
    }
    int dist[Maxnn], path[Maxnn];
    int s[Maxnn];//标记已经找到的最短路径的顶点
    int i, j, k;
    int mindis;
    for (i = 0; i < g.vexnum; i++)
    {
        dist[i] = g.arcs[v][i];//距离初始化
        s[i] = 0;//0表示未找到最短路径
        if (dist[i] < INFINITY)//路径初始化,即 最开始的路径设为起始位置
            path[i] = v;
        else
            path[i] = -1;
    }
    s[v] = 1;//即起始位置最短路径 为 本身
    for (i = 0; i < g.vexnum; i++)//对剩余顶点遍历,直到求出v到其余所有顶点的最短路径
    {
        mindis = INFINITY;
        k = v;
            for (j = 0; j < g.vexnum; j++)//选出V的边权重和最短的点,并且未被设置未最短路径
            {
                if (s[j] == 0 && dist[j] < mindis)
                {
                    k = j; //最短的那个点
                    mindis = dist[j];//最短的权重即路径
                }
            }
            s[k] = 1;//将该点设为最短路径点
            for (j = 0; j < g.vexnum; j++)//修改V到该点的路径长
            {
                if (s[j] == 0 && g.arcs[k][j] < INFINITY && dist[k] + g.arcs[k][j] < dist[j])//当前点到原点+当前点到下一个点<原点到下一个点
                {
                    dist[j] = dist[k] + g.arcs[k][j];
                    path[j] = k;
                }
            }
    }
    dispath(dist, path, s, g.vexnum, v,g);//输出最短路径
}
void ppath(int path[][Maxnn], int a, int b,mgraph g)
{
    int k;
    k = path[a][b];
    if (k == -1)//a到b直达
    {
        printf("v%d.%s->",g.vexs[b].position, g.vexs[b].name);
    }
    else
    {
        ppath(path, a, k, g);
        //printf("v%s->",g.vexs[k].name);
        ppath(path, k, b, g);
    }
}
void dispath_floyd(int A[][Maxnn], int path[][Maxnn], int n,mgraph g)
{
    int a, b;
    printf("请输入起始点与目的地:");
    scanf("%d %d", &a, &b);
    printf("\n");
    while (a >= g.vexnum || b >= g.vexnum)
    {
        printf("输入有误请重新输入:");
        scanf("%d %d", &a, &b);
    }
    if (A[a][b] == INFINITY)
    {
        if (a != b)
        {
            printf("从v%d.%s到v%d.%s没有路径\n", g.vexs[a].position, g.vexs[a].name,g.vexs[b].position, g.vexs[b].name);
        }
    }
    else
    {
        printf("从v%d.%s到v%d.%s路径为:",g.vexs[a].position,g.vexs[a].name,g.vexs[b].position, g.vexs[b].name);
        printf("v%d.%s->",g.vexs[a].position, g.vexs[a].name);
        ppath(path, a, b,g);
        printf("路径长度为:%d\n", A[a][b]);
    }
    
}
void InquireAToB_shortest(mgraph g)
{
    int A[Maxnn][Maxnn];//存储路径长
    int path[Maxnn][Maxnn];//存储中间点
    int i, j, v;
    for (i = 0; i < g.vexnum; i++) //初始化
    {
        for (j = 0; j < g.vexnum; j++)
        {
            A[i][j] = g.arcs[i][j];
            path[i][j] = -1;
        }
    }

    for (v = 0; v < g.vexnum; v++) //依次加入中间点
    {
        for (i = 0; i < g.vexnum; i++)//行
        {
            for (j = 0; j < g.vexnum; j++)//列
            {
                if (A[i][j] > A[i][v] + A[v][j])
                {
                    A[i][j] = A[i][v] + A[v][j];//更新最短路径
                    path[i][j] = v;//更新存储中间点
                }
            }
        }
    }
    dispath_floyd(A,path, g.vexnum,g);//输出最短路径
}
void PrintfCampus(mgraph g)
{
    int i, j;
    for (i = 0; i < g.vexnum; i++)
    {
        for (j = 0; j < g.vexnum; j++)
        {
            if (g.arcs[i][j] == INFINITY)
            {
                printf("-   ");
            }
            else
            printf("%d   ", g.arcs[i][j]);
        }
        printf("\n");
    }
}
int locatevex(mgraph g, int v)
{
    int i;
    for (i = 0; i < g.vexnum; i++)
    {
        if (v == g.vexs[i].position)
            return i;
    }
    return -1;
}
int creatgraph(mgraph * g)
{
    int i, j;
    int v0, v1, distance;
    int m, n;
    printf("请输入图的顶点数与边数:\n");
    scanf("%d %d", &g->vexnum, &g->arcnum);
    printf("下面请输入景点信息:\n");
    for (i = 0; i < g->vexnum; i++)
    {
        printf("请输入景点编号:");
        scanf("%d", &g->vexs[i].position);
        printf("\n请输入景点名称:");
        scanf("%s", g->vexs[i].name);
        printf("\n请输入景点介绍:");
        scanf("%s", g->vexs[i].introduction);
    }
    for (i = 0; i < g->arcnum; i++)
    {
        for (j = 0; j < g->arcnum; j++)
            if (i == j)
                g->arcs[i][j] = 0;
            else
            g->arcs[i][j] = INFINITY;
    }
    printf("\n下面输入景点边的信息:");
    for (i = 1; i <= g->arcnum; i++)
    {
        printf("\n输入景点的起始点、终点与长度为:");
        scanf("%d%d%d", &v0, &v1, &distance);
        m = locatevex(campus, v0);
        n = locatevex(campus, v1);
        if (m >= 0 && n >= 0)
        {
            g->arcs[m][n] = distance;
            g->arcs[n][m] = g->arcs[m][n];
        }
    }
    return 1;
}
int DeleteVex(mgraph* g)
{
    int i, j;
    int m;
    int v;
    if (g->vexnum < 0)
    {
        printf("图中已无顶点\n");
    }
    printf("请输入想要删除的景点编号:");
    scanf("%d", &v);
    while (v<0 || v>g->vexnum)
    {
        printf("输入有误请重新输入:");
        scanf("%d", &v);
    }
    m = locatevex(campus, v);
    if (m < 0)
    {
        printf("该顶点已经删除");
        return 1;
    }
    for (i = m; i < g->vexnum-1; i++)
    {
        g->vexs[i].position = g->vexs[i+1].position;
        strcpy(g->vexs[i].name,g->vexs[i + 1].name) ;
        strcpy(g->vexs[i].introduction, g->vexs[i+1].introduction);
    }
    for (i = m; i < g->arcnum-1; i++)
    {
        for (j = 0; j < g->arcnum; j++)
        {
            g->arcs[i][j] = g->arcs[i + 1][j];
            g->arcs[j][i] = g->arcs[i][j];
        }
    }
    g->vexnum--;
    return 1;    
}
int DeleteArc(mgraph* g)
{
    int v0, v1;
    int m,n;
    if (g->arcnum < 0)
    {
        printf("图中已无边可删");
        return 1;
    }
    printf("请输入要删除边的起始点与终点:");
    scanf("%d %d", &v0, &v1);
    m = locatevex(campus, v0);
    if (m < 0)
    {
        printf("该顶点已经被删除");
        return 1;
    }
    n = locatevex(campus, v1);
    if (n < 0)
    {
        printf("该顶点已经被删除");
        return 1;
    }
    g->arcs[m][n] = INFINITY;
    g->arcs[n][m] = INFINITY;
    g->arcnum--;
    return 1;
}
int AddVex(mgraph* g)
{
    int m, v;
    int i, j;
    printf("请输入要新增景点的信息:");
    printf("景点编号:");
    scanf("%d", &g->vexs[g->vexnum].position);
    printf("景点名称:");
    scanf("%s", g->vexs[g->vexnum].name);
    printf("景点介绍:");
    scanf("%s", g->vexs[g->vexnum].introduction);
    g->vexnum++;
    for (i = 0; i < g->vexnum; i++)
    {
        g->arcs[i][g->vexnum - 1] = INFINITY;
        g->arcs[g->vexnum - 1][i] = INFINITY;
    }
    return 1;
}
int AddArc(mgraph* g)
{
    int v0, v1;
    int distance;
    printf("\n请输入边的起始点与终点、边长:");
    scanf("%d%d%d", &v0, &v1, &distance);
    while (v0<0 || v0>g->vexnum || v1<0 || v1>g->vexnum)
    {
        printf("输入错误,重新输入:");
        scanf("%d%d", &v0, &v1);
    }
    if (locatevex(campus, v0) < 0)
    {
        printf("此结点已经删除");
        return 1;
    }
    if (locatevex(campus, v1) < 0)
    {
        printf("此结点已经删除");
        return 1;
    }
    g->arcs[v0][v1] = distance;
    g->arcs[v1][v0] = distance;
    return 1;
}
int FixGraph(mgraph* g)
{
    int changenum;
    int i, j;
    int m,n;
    int v0, v1, distance;
    printf("请输入要修改的景点个数:");
    scanf("%d", &changenum);
    while (changenum < 0 || changenum > g->vexnum)
    {
        printf("输入有误请重新输入:");
        scanf("%d", &changenum);
    }
    for (i = 0; i < changenum; i++)
    {
        printf("\n请输入景点编号:");
        scanf("%d", &m);
        n = locatevex(campus, m);
        printf("\n请输入景点的名称:");
        scanf("%s", g->vexs[n].name);
        printf("\n请输入景点的简介:");
        scanf("%s", g->vexs[n].introduction);
    }
    printf("\n下面请输入要修改的边数:");
    scanf("%d", &changenum);
    while (changenum < 0 || changenum > g->vexnum)
    {
        printf("输入有误请重新输入:");
        scanf("%d", &changenum);
    }
    for(i = 0;i<changenum;i++)
    {
        printf("\n修改的第%d条边的起点 终点 长度为:", i+1);
        scanf("%d %d %d", &v0, &v1, &distance);
        m = locatevex(campus, v0);
        n = locatevex(campus, v1);
        if (m >= 0 && n >= 0)
        {
            g->arcs[m][n] = distance;
            g->arcs[n][m] = distance;
        }
    }
    return 1;
}
int ChangeGraph(mgraph * g)
{
    int choice;
    printf("\n 请问是要\n\n  (1)再次建图   (2)删除结点   (3)删除边 \n");
    printf("\n  (4)新增结点   (5)增加边     (6)更新信息 \n");
    printf("\n  (7)打印邻接矩阵             (8)返回?\n\n");
    scanf("%d", &choice);
    printf("\n");
    while (!(choice == 1 || choice == 2 || choice == 3 || choice == 4 || choice == 5 || choice == 6 || choice == 7 || choice == 8))
    {
        printf("输入选择不明确,请重输\n");
        scanf("%d", &choice);
    }
    while (1)
    {
        switch (choice)
        {
        case 1:creatgraph(g); break; //重建图
        case 2:DeleteVex(g); break;//删除顶点
        case 3:DeleteArc(g); break;//删除边
        case 4:AddVex(g); break;//新增结点
        case 5:AddArc(g); break;//增加边
        case 6:FixGraph(g); break;//修改图
        case 7:PrintfCampus(campus); break;//输出邻接矩阵
        case 8:return 1; //返回主菜单
        }
        printf("\n 请问是要\n\n  (1)再次建图   (2)删除结点   (3)删除边 \n");
        printf("\n  (4)新增结点   (5)增加边     (6)更新信息 \n");
        printf("\n  (7)打印邻接矩阵             (8)返回?\n\n");
        scanf("%d", &choice);
        while (!(choice == 1 || choice == 2 || choice == 3 || choice == 4 || choice == 5 || choice == 6 || choice == 7 || choice == 8))
        {
            printf("输入选择不明确,请重输\n");
            scanf("%d", &choice);
        }
    }
}
int main()
{
    int n;
    int select;
    campus = Init();//初始化校园信息
    //mgraph school = campus;
    do {
        system("cls");
        select = Menu();
        switch (select)
        {
        case 1://学院景点介绍
            IntroductionCampus(campus);
            break;
        case 2://查看浏览路线  输入位置,输出该位置到其他位置的路线
            FromBeginToSth_Dijkstra(campus);//Dijkstra,求某个顶点到其余各顶点的最短路径
            break;
        case 3://查询景点间最短路径   Floyd算法
            InquireAToB_shortest(campus);
            break;
        case 4://更改图的信息
            ChangeGraph(&campus);
            break;
        case 5:打印学校平面图
            PrintfCampus(campus);
            break;
        case 0://退出
            break;
        }
        printf("\n\n");
        system("pause");
    } while (select != 0);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值