C语言开发东北大学活力长者社区班车路线管理(迪杰斯特拉算法)

本文展示了一个使用C语言开发的班车路线管理系统,该系统运用迪杰斯特拉算法来计算两个站点之间的最短路径。程序包括读取和写入文件、新增班车路线、查找站点以及显示最短路径等功能,实现了对班车路线的动态管理和优化。
摘要由CSDN通过智能技术生成

东北大学大作业-活力长者社区-班车路线管理(创新)

开发语言:c语言

编译工具:vscode

引用的小伙伴麻烦点下关注,有任何疑问欢迎大家留言哎

1.运行效果

2.迪杰斯特拉算法实现思路

为了求得两站点间的最短路径,需要建立3个数组分别是final[M],dist[M], path[M](代码中命名有所不同)。final负责标记各顶点是否已经找到最短路径,dist负责记录目前能够找到的最短的最优的一条路径。path负责记录最短最优路径的前驱。如下图所示。

之后,需要对三个数组分别进行初始化,初始化完成后正式开始执行算法,首先循环遍历所有结点,找到没有确定最短路径且dist值最小的顶点,将其final值设为TRUE。然后需要检查其邻节点,若final为FALSE且本轮dist值最小的顶点dist值加上该顶点到邻节点距离小于邻节点的dist值时,需要更新dist和path信息。之后继续循环遍历所有节点,执行之上操作,直至终点的final值为TRUE为止。终点的dist值即为最短路径长度,通过path数组也可以找点具体的最短路径。

3.完整代码

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
#include <malloc.h>

#define BUFF 1024
# define TRUE 1
# define FALSE 0
# define OK 1
# define ERROR 0
# define OVERFLOW -2
# define M 100 //定义车站最大数量

//定义路径
typedef struct Route{
    int iPF; //边上节点i
    int jPF; //边上节点j

    double len;//路径长度

    struct Route *iLink; //依附于节点i的下一节点
    struct Route *jLink; //依附于节点j的下一节点
}Route, *RT;

//定义车站
typedef struct PlatNode{
    char name[10];//车站名称
    Route *first; //第一条路径
}PlatNode, PlatForm[M];

//定义路线图
typedef struct RtGNode{
    PlatForm platList;
    int plnum, rtnum;//车站数量,路径数量

}RtGNode, *RtGraph;

//**************************************班车路线管理函数定义**************************************************
//班车路线管理控制函数
void sRouteControl();

//班车路线管理页面函数
void sRoutePage();
void sRouteChoosePage(RtGraph G);
void addRtNodePage(RtGraph G);
void minRoutePage(RtGraph G);

//班车路线管理文件处理函数
int readRtGraph(RtGraph G);
int writeRtGraph(RtGraph G);

//班车路线管理操作函数
int addRTNode(RtGraph G,char *name);
void printfPlatForm(RtGraph G);
int findPlatForm(RtGraph G, char* pName);
void clearRTFile();

//迪杰斯特拉算法函数定义
void dijkstra(RtGraph G, int begin, int end);

//定义顶点
int main()
{
    sRouteControl();
    return 0;
}

//********************
//**************************************班车路线管理函数实现***************************************************
//********************

//**************************************班车路线管理页面函数实现***********************************************
void sRouteControl(){



    sRoutePage();
    RtGraph G = (RtGraph)malloc(sizeof(RtGNode));
    readRtGraph(G);

    printf("                                                按任意键开始");
    getchar();
    system("cls");

    sRouteChoosePage(G);

    free(G);
}

void sRoutePage(){
    system("cls");
    color(2);
    printf("                                       **********************************\n");
    color(7);
    printf("                                       **********************************\n");
    color(6);
    printf("                                       ******欢迎来到班车路线管理!******\n");
    color(7);
    printf("                                       **********************************\n");
    color(2);
    printf("                                       **********************************\n");
    color(7);

}

void sRouteChoosePage(RtGraph G){
   while(1){
        system("cls");

        int num;

        printf("\n===============================\n");
        color(6);
        printf("1.新增班车路线\n2.求站点间最短路径\n3.清空班车路线图\n4.保存并退出系统\n");
        color(7);
        printf("\n===============================\n\n");

        printf("请输入您所选的数字:");

        scanf("%d",&num);

        switch (num){
            case 1:
                addRtNodePage(G);
                writeRtGraph(G);
                break;

            case 2:
                minRoutePage(G);
                break;

            case 3:
                clearRTFile();
                break;

            case 4:
                return;

            default:
                printf("错误!");
                printf("    你所输入数字不存在:");
                break;
            }
    }
}

//新增班车站点页面
void addRtNodePage(RtGraph G){

    char name[10];
    int j;

    while(1){
        system("cls");
        color(7);
        printf("\n=======================================\n");
        color(6);
        printf("请按指示录入新建班车路线信息\n");
        color(7);
        printf("=======================================\n\n");

        printf("现已有站点如下所示:\n");
        printfPlatForm(G);

        color(7);
        printf("\n=========================================\n");
        color(6);
        printf("请输入新建班车路线站点名称(小于等于10个字符):");

        scanf("%s",&name);

        if(addRTNode(G, name)){
            printf("\n接下来请为班车站点%s建立班车路线", G->platList[G->plnum-1].name);
            addRoutePage(G, G->plnum - 1);
        }

        printf("\n请选择下一步操作 按1表示返回班车路线管理主页面,否则继续新建:\n");
        scanf("%d",&j);

        if(j == 1){
            return;
        }
    }

}

//新增班车路线页面
void addRoutePage(RtGraph G, int RF){
    color(7);
    printf("\n=========================================\n");
    color(6);
    char name[10];
    double len;
    int j;

    while(1){
        printf("\n请输入另一端班车路线站点名称(小于等于10个字符):");
        scanf("%s", &name);
        int RS = findPlatForm(G, name);

        if(RS == -1){
            printf("输入节点不存在,请重新输入\n");
        }else{
            printf("请输入班车路线长度:");
            scanf("%lf", &len);
            addRoute(G, RF, RS, len);
        }
        printf("\n请选择下一步操作 按1表示结束新建班车路线,否则继续新建:\n");
        scanf("%d",&j);

        if(j == 1){
            return;
        }
    }

}

//最短路径页面
void minRoutePage(RtGraph G){
        char begin[10];
        char end[10];
        int begin_num;
        int end_num;
        int j;

        while(1){
            system("cls");
            color(7);
            printf("\n=======================================\n");
            color(6);
            printf("现使用迪杰斯特拉算法求最短路径\n");
            color(7);
            printf("=======================================\n\n");

            printf("现已有站点如下所示:\n");
            printfPlatForm(G);

            color(7);
            printf("\n=========================================\n");
            color(6);

            printf("请输入班车出发站点名称(小于等于10个字符):");
            scanf("%s",&begin);
            begin_num = findPlatForm(G, begin);

            printf("\n请输入班车到达站点名称(小于等于10个字符):");
            scanf("%s", &end);
            end_num = findPlatForm(G, end);

            if(begin_num == -1 || end_num == -1){
                printf("班车站点不存在\n");
            }else{
                dijkstra(G, end_num, begin_num);
            }

            printf("\n请选择下一步操作 按1表示返回班车路线管理主页面,否则继续:\n");
            scanf("%d",&j);

            if(j == 1){
                return;
            }
    }

}

//********************
//**************************************页面颜色设计函数实现**********************************************
//********************

void color(int x){
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),x);
}

//**************************************班车路线管理文件处理函数实现*******************************************

//从文件中读取路径
int readRtGraph(RtGraph G){

    G->plnum = 0;
    G->rtnum = 0;

    printf("开始读取文件");
    char line[BUFF] = {0};//打开文件流
    FILE* file;
    file = fopen("D:\\RtGraph.txt","r");

    if(file){
        while (fgets(line, BUFF, file) != NULL) {
            strtok(line, "\n");//截取有效字符串
            printf("截取的有效字符串为:%s\n", line);

            if(!line){
                break;
            }

            //***
            //*
            //**下面开始构建站点
            //*
            //***

            char* str1 = strtok(line, "-");//截取站点1名称
           printf("读取站点1名称为:%s\n", str1);

            int pF = findPlatForm(G, str1);

            //如果站点不存在,则构建新的站点
            if(pF == -1){
                strcpy(G->platList[G->plnum].name, str1);
               printf("新增站点名称为:%s\n", G->platList[G->plnum].name);

                G->platList[G->plnum].first = NULL;
                pF = G->plnum;
                G->plnum++;
            }

            char* str2 = strtok(NULL, "-");//截取站点2名称
            printf("读取站点2名称为:%s\n", str2);

            int pS = findPlatForm(G, str2);

             //如果站点不存在,则构建新的站点
            if(pS == -1){
                strcpy(G->platList[G->plnum].name, str2);
                printf("新增站点名称为:%s\n", G->platList[G->plnum].name);

                G->platList[G->plnum].first = NULL;

                pS = G->plnum;
                G->plnum++;
            }

            //***
            //*
            //**下面开始构建边
            //*
            //***

            char *lenStr = strtok(NULL, "-");//截取路线距离
            //头插法

            //首先申请给内存动态分配空间
            RT rt = (RT)malloc(sizeof(Route));
            G->rtnum++;

            rt->len = atof(lenStr);
            rt->iPF = pF;
            rt->jPF = pS;
            rt->iLink = NULL;
            rt->jLink = NULL;

            rt->iLink = G->platList[pF].first;
            rt->jLink = G->platList[pS].first;

            G->platList[pF].first = rt;
            G->platList[pS].first = rt;
        }
    }else{
  //      printf("文件打开失败\n");
            return ERROR;
    }

    fclose(file);//关闭文件流

    return OK;
}

int writeRtGraph(RtGraph G){

    //是否访问过边
    int visit[G->rtnum][G->rtnum];

    for(int i = 0; i < G->rtnum; i++){
            for(int j = 0; j < G->rtnum; j++){
                visit[i][j] = FALSE;
            }
    }

        FILE* file = fopen("D:\\RtGraph.txt", "w+");//文件

    printf("向文件中存入数据如下所示:\n");
    for(int z = 0; z < G->plnum; z++){
        //遍历站点连接的边
        RT R = G->platList[z].first;
        while(R){
            if(!visit[R->iPF][R->jPF]){

                printf("%s-%s-%lf\n", G->platList[R->iPF].name, G->platList[R->jPF].name, R->len);
                fprintf(file, "%s-%s-%lf\n", G->platList[R->iPF].name, G->platList[R->jPF].name, R->len);

                visit[R->iPF][R->jPF] = TRUE;
            }
           // printf("\n读取一个子节点\n");
            if(z == R->iPF){
                R = R->iLink;
            }else if(z == R->jPF){
                R = R->jLink;
            }

        }
    }
    fclose(file);//关闭文件流
    return OK;
}

//**************************************班车路线管理操作函数实现********************************************

//新增站点
int addRTNode(RtGraph G,char *name){

    if(G->plnum == M){
        printf("班车路线站点已满,无法新建\n");
        return ERROR;
    }
    if(findPlatForm(G, name) != -1){
        printf("改路线结点已存在\n");
        return ERROR;
    }
    strcpy(G->platList[G->plnum].name, name);
    G->platList[G->plnum].first = NULL;

    G->plnum ++;

    printf("班车路线节点%s已经建立\n", G->platList[G->plnum-1]);
    return OK;
}

//新增路线
int addRoute(RtGraph G, int pF, int pS, double Rlen){

     if(pF == -1 || pS == -1){
        printf("路线两边站点不存在年\n");
        return ERROR;
     }

    //首先申请给内存动态分配空间
    RT rt = (RT)malloc(sizeof(Route));
    G->rtnum++;

    rt->len = Rlen;
    rt->iPF = pF;
    rt->jPF = pS;
    rt->iLink = NULL;
    rt->jLink = NULL;

    rt->iLink = G->platList[pF].first;
    rt->jLink = G->platList[pS].first;

    G->platList[pF].first = rt;
    G->platList[pS].first = rt;
    printf("路线构建完成\n");

    return OK;
}

void printfPlatForm(RtGraph G){
    printf("\n");
    for(int i = 0; i < G->plnum; i++){
        color(2);
        printf("%s\n", G->platList[i].name);
    }
}

//发现站点
int findPlatForm(RtGraph G, char* pName){

    for(int i = 0; i  < G->plnum; i++){

        //如果发现
        if(!strcmp(G->platList[i].name, pName)){
            return i;
           }
    }
    //如果没有发现
    return -1;
}

//清空文件
void clearRTFile(){
    FILE *file;
    file  = fopen("D:\\RtGraph.txt", "w+");
    fclose(file);
    printf("清空文件成功\n");
}
//**************************************迪杰斯特拉算法函数实现********************************************

//迪杰斯特拉算法求最短路径
void dijkstra(RtGraph G, int begin, int end){

    int finalRt[G->plnum];//标记各顶点是否找到最短路径
    double distRt[G->plnum];//最短路径长度
    int pathRt[G->plnum];//路径上的前驱
    int min;
    color(7);


    color(2);
    printf("\n现在开始运行迪杰斯特拉算法\n");
    printf("\n===============================\n");


    //****************
    //**算法首先要进行初始化操作
    //****************

    printf("\n算法首先要进行初始化操作\n");
    int i = 0;
    //首先对finalRt数组进行初始化
    for(i = 0; i < G->plnum; i++){
        finalRt[i] = FALSE;
    }
    finalRt[begin] = TRUE;

    //对最短路径长度进行初始化
    for(int j = 0; j < G->plnum; j++){
        distRt[j] = -1; //使用-1表示无穷
    }
    distRt[begin] = 0;

    printf("%s已经确定最短路径为:%d\n", G->platList[begin], distRt[begin]);

    //对路径前驱进行初始化
    for(int z = 0; z < G->plnum; z++){
        pathRt[z] = -1; //-1表示暂无前驱节点
    }
    RT R = G->platList[begin].first;



    while(R){
       if(begin == R->iPF){
            distRt[R->jPF] = R->len;
            pathRt[R->jPF] = R->iPF;

            R = R->iLink;
        }else if(begin == R->jPF){
            distRt[R->iPF] = R->len;
            pathRt[R->iPF] = R->jPF;

            R = R->jLink;
        }
    }



     //****************
     //**算法正式开始执行
     //****************

     printf("\n算法正式开始执行\n");

    while(!finalRt[end]){
        //首先循环遍历所有结点,找到没有确定最短路径且,distRt值最小的顶点

        min = -1; //distRt最小的结点
        for(i = 0; i < G->plnum; i++){
            if(!finalRt[i]){
                if(distRt[i] != -1 && min == -1){//如果最小顶点没被确定
                    min = i;
                }else if(distRt[i] != -1 && distRt[i] < distRt[min]){//确定了但有更小的(不为无穷)
                    min = i;
                }
            }
        }
        //找到distRt值最小的顶点后,将finalRt设为TRUE
        finalRt[min] = TRUE;
        printf("已经确定最短路径%s至%s为:%lf\n", G->platList[pathRt[min]], G->platList[min], distRt[min]);

        //检查其邻节点, 若final为FALSE,更新dist和path信息
        R = G->platList[min].first;



        while(R){
            if(min == R->iPF){
                //更新dist信息
                if(distRt[R->jPF] == -1 || distRt[R->jPF] > distRt[min] + R->len){
                    distRt[R->jPF] = distRt[min] + R->len;
                    printf("%s的distRt已更新为:%lf\n", G->platList[R->jPF], distRt[R->jPF]);

                    //更新path信息
                    pathRt[R->jPF] = R->iPF;
                }
                R = R->iLink;

            }else if(min == R->jPF){
                //更新dist信息
                if(distRt[R->iPF] == -1 || distRt[R->iPF] > distRt[min] + R->len){
                    distRt[R->iPF] = distRt[min] + R->len;
                    printf("%s的distRt已更新为:%lf\n", G->platList[R->iPF], distRt[R->iPF]);

                    //更新path信息
                    pathRt[R->iPF] = R->jPF;
                }

                R = R->jLink;
            }
        }
    }

    printf("\n===============================\n");

    color(6);
    printf("\n经迪杰斯特拉算法,可求得从%s至%s班车的最短路径大小为:%lf", G->platList[end],
           G->platList[begin], distRt[end]);

    i = end;
    printf("\n\n其最短路径为:");
    while(i != -1){
        printf("%s", G->platList[i].name);
        i = pathRt[i];
        if(i != -1) printf("-->");
    }
    printf("\n");
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值