c++实现北京地铁线路查询系统

该程序实现了基于Dijkstra算法和Floyd算法的北京地铁线路查询,从输入的起点和终点站名,找出最短换乘路径。用户可以查询任意两个站点间的最优乘车方案。程序读取bgstations.txt文件中的地铁站信息进行建模并计算。
摘要由CSDN通过智能技术生成
//使用前将bgstations.txt(文件的内容在代码末尾)放在与cpp文件的同一位置
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
#define MAX 9999
#define N 20    /*最长站名*/
#define NUM 599 /*最大站数*/


typedef struct{      /*车站信息*/
    char station[N]; /*站名称*/
    int change;      /*换乘状态,1为是,0为否*/
}sta;

typedef struct{      /*相邻两站信息*/
    int weight;      /*两站之间的距离为1*/
    int L;           /*两站所在的线号*/
}G;

sta vertex[NUM];     /*地铁图顶点数组*/
G graph[NUM][NUM];   /*图权重数组*/

int Vsum;            /*实际地铁站数*/
int path[NUM];       /*换乘路径*/
int s[NUM];          /*起始站到其它站最短路是否找到*/
int dis[NUM];        /*起始站到其他站的最短距离*/

int cout[NUM];       /*存储路径的栈*/
int top=-1;


/*---------------------------------------------------*/
void push(int v);
int empty();
int pop();
int search(char *s);
void create(int LINE);
void dijkstra(int V1,int V2);
void floyd(int V1,int V2);
void print(int V1,int V2);
void make();
void program();
/*---------------------------------------------------*/


void push(int v){/*入栈*/
    if(top==NUM) return;
    cout[++top]=v;
}

int empty(){/*栈是否为空*/
    if(top<0) return 1;
    return 0;
}

int pop(){/*出栈*/
    if(empty())return -1;
    return cout[top--];
}

int search(char *s){/*查找站是否存在*/
    int i;
    for(i=0;i<Vsum;i++)
        if(!strcmp(vertex[i].station,s))
            return i;
    return -1;
}

void create(int LINE){/*建图*/
    while(LINE--){
        int no,sum;            /*每条线路的编号和站数*/
        scanf("%d %d ",&no,&sum);
        printf("\n%d号线 共%d个站\n\n",no,sum);
        int last=-1;                         /*上一站*/
        while(sum--){            /*存储时注意站会重复*/
            char name[N];
            int is;
            scanf("%s %d ",name,&is);
            if(is==1){
            	printf("%s(换乘) -> ",name);
			}else{
				printf("%s -> ",name);
			} 
            
            /*查找该站是否已存在*/
            int index=search(name);
            if(index==-1){                   /*不存在*/
                strcpy(vertex[Vsum].station, name);
                vertex[Vsum].change=is;
                if(last!=-1){
                    graph[last][Vsum].L=graph[Vsum][last].L=no;
                    graph[last][Vsum].weight=graph[Vsum][last].weight=1;
                }
                last=Vsum;               /*更新上一站*/
                Vsum++;                    /*更新顶点*/
            }else{                             /*存在*/
                if(last!=-1){
                    graph[last][index].L=graph[index][last].L=no;
                    graph[last][index].weight=graph[index][last].weight=1;
                }
                last=index;              /*更新上一站*/
            }
        }
        printf("\n");
    }
}
//迪杰斯特拉算法 
void dijkstra(int V1,int V2){
    int i;
    /*初始化*/
    for(i=0;i<Vsum;i++){
        dis[i]=graph[V1][i].weight;
        s[i]=0;
        path[i]=V1;
    }
    dis[V1]=0;
    s[V1]=1;
    int minweight,v=-1,j;
    for(i=0;i<Vsum-1;i++){
        minweight=MAX;
        /*找到未标记的最小权重值顶点 */
        for(j=0;j<Vsum;j++){
            if(!s[j]&&dis[j]<minweight){
                v=j;
                minweight=dis[v];
            }
        }
        s[v]=1;                /*标记顶点已找到最短路*/
        if(v==V2) return;          /*终点已标记则返回*/
        for(j=0;j<Vsum;j++){
            if(!s[j]&&graph[v][j].L&&minweight+graph[v][j].weight<dis[j]){
                dis[j]=minweight+graph[v][j].weight;
                path[j]=v;       /*记录路径的前驱顶点*/
            }
        }
    }
}
//弗洛伊德算法 
void floyd(int V1,int V2){
    int i,j,k;
    int p_ath[NUM][NUM];
    /*初始化路径*/
    for(i=0;i<Vsum;i++)
        for(j=0;j<Vsum;j++)
            if(i!=j&&graph[i][j].weight<MAX)
                p_ath[i][j]=i;
    for(k=0;k<Vsum;k++)
        for(i=0;i<Vsum;i++)
            for(j=0;j<Vsum;j++)
                if(graph[i][j].weight>graph[i][k].weight+graph[k][j].weight){
                    graph[i][j].weight=graph[i][k].weight+graph[k][j].weight;
                    p_ath[i][j]=p_ath[k][j];
                }
    int t=V2;
    for(;t!=V1;t=p_ath[V1][t])              /*路径追溯*/
        push(t);
}

void print(int V1,int V2){
    int last=V1;                            /*保存上一站*/
    int k=1;                               /*乘坐站数*/
    int u=pop();                             /*下一站*/
    int L=graph[last][u].L;                /*乘坐线路*/
    printf("最佳方案:%s-%d号线(",vertex[V1].station,L);
    last=u;                              /*更新上一站*/
    while(!empty()){
        u=pop();
        if(L!=graph[last][u].L){           /*需要换乘*/
            L=graph[last][u].L;
            /*打印乘坐站数和此换乘站*/
            printf("共%d站)-%s-%d号线(",k,vertex[last].station,L);
            k=0;
        }
        k++;
        last=u;                      /*更新上一站*/
    }
    printf("共%d站)-%s\n",k,vertex[V2].station);
}

void dp(int V1,int V2){
    int f[NUM]={MAX},p_ath[NUM]={V1};
    f[Vsum-1]=0;
    int i,j;
    for(i=Vsum-2;i>=0;i--){
        for(j=i+1;j<Vsum;j++){
            if(f[j]<MAX&&graph[i][j].weight+f[j]<f[i]){
                f[i]=graph[i][j].weight+f[j];
                p_ath[i]=j;
            }
        }
    }
    int t=V2;
    for(;t!=V1;t=p_ath[t])  push(t);
}

/*---------------------------------------------------*/

void make(){
	printf("\n-----北京地铁乘坐线路查询系统-----\n");
    printf("\n1.查询线路\n");
    printf("2.退出查询\n");
    int op;
    printf("请输入:"); 
    scanf("%d",&op);
    if(op==1) program();
    else{
    	printf("\n欢迎下次使用!\n"); 
		return;
	} 
}

void program(){
    int V1,V2;
    printf("请输入起始站名和终点站名,两站之间用回车分开\n");
    /*输入起始站和终点站*/
    char name_start[N],name_end[N];
    scanf("%s %s",name_start,name_end);
    printf("\n");
    V1=search(name_start);
    V2=search(name_end);
/*---------------------------------------------------*/
    /*查询换乘*/
    dijkstra(V1,V2);
    int t=V2;
    for(;t!=V1;t=path[t])  push(t);       /*路径追溯*/
    //floyd(V1,V2);
    //dp(V1,V2);
    /*打印结果*/
    print(V1,V2);
    make();
}

int main(){
    freopen("bgstations.txt","r",stdin);
    int LINE;                            /*地铁总线数*/
    scanf("%d ",&LINE);
    int i,j;
    /*初始化*/
    for(i=0;i<NUM;i++)
        for(j=0;j<NUM;j++){
            graph[i][j].weight=graph[j][i].weight=MAX;
            graph[i][j].L=graph[j][i].L=0;
        }
/*---------------------------------------------------*/
    /*建图*/
    create(LINE);
    freopen("CON", "r", stdin);
/*--------------------------------------------------*/
    /*查找起始站与终点站对应的顶点编号*/
    make();
    system("pause");
    return 0;
}

bgstations.txt中的内容:
12
1 23
苹果园 0
古城 0
八角游乐园 0
八宝山 0
玉泉路 0
五棵松 0
万寿路 0
公主坟 1
军事博物馆 1
木樨地 0
南礼士路 0
复兴门 1
西单 1
天安门西 0
天安门东 0
王府井 0
东单 1
建国门 1
永安里 0
国贸 1
大望路 1
四惠 1
四惠东 1

2 19
西直门 1
积水潭 0
鼓楼大街 1
安定门 0
雍和宫 1
东直门 1
东四十条 0
朝阳门 1
建国门 1
北京站 0
崇文门 1
前门 0
和平门 1
宣武门 1
长椿街 0
复兴门 1
阜成门 0
车公庄 1
西直门 1

4 24
安河桥北 0
北宫门 0
西苑 0
圆明园 0
北京大学东门 0
中关村 0
海淀黄庄 1
人民大学 0
魏公村 0
国家图书馆 1
动物园 0
西直门 1
新街口 0
平安里 1
西四 0
灵境胡同 0
西单 1
宣武门 1
菜市口 1
陶然亭 0
北京南站 1
马家堡 0
角门西 1
公益西桥 1

5 23
宋家庄 1
刘家窑 0
蒲黄榆 1
天坛东门 0
磁器口 1
崇文门 1
东单 1
灯市口 0
东四 1
张自忠路 0
北新桥 0
雍和宫 1
和平里北街 0
和平西桥 0
惠新西街南口 1
惠新西街北口 0
大屯路东 1
北苑路北 0
立水桥南 0
立水桥 1
天通苑南 0
天通苑 0
天通苑北 0

6 27
海淀五路居 0
慈寿寺 1
花园桥 0
白石桥南 1
车公庄西 0
车公庄 1
平安里 1
北海北 0
南锣鼓巷 1
东四 1
朝阳门 1
东大桥 0
呼家楼 1
金台路 1
十里堡 0
青年路 0
褡裢坡 0
黄渠 0
常营 0
草房 0
物资学院路 0
通州北关 0
通运门 0
北运河西 0
郝家府 0
东夏园 0
潞城 0

7 20
北京西站 1
湾子 0
达官营 0
广安门内 0
菜市口 1
虎坊桥 0
珠市口 0
桥湾 0
磁器口 1
广渠门内 0
广渠门外 0
九龙山 1
大郊亭 0
百子湾 0
化工 0
南楼梓庄 0
欢乐谷景区 0
垡头 0
双合 0
焦化厂 0

8 18
朱辛庄 1
育知路 0
平西府 0
回龙观东大街 0
霍营 1
育新 0
西小口 0
永泰庄 0
林萃桥 0
森林公园南门 0
奥林匹克公园 1
奥体中心 0
北土城 1
安华桥 0
安德里北街 0
鼓楼大街 1
什刹海 0
南锣鼓巷 1

9 13
郭公庄 1
丰台科技园 0
科怡路 0
丰台南路 0
丰台东大街 0
七里庄 1
六里桥 1
六里桥东 0
北京西站 1
军事博物馆 1
白堆子 0
白石桥南 1
国家图书馆 1

10 46
巴沟 0
苏州街 0
海淀黄庄 1
知春里 0
知春路 1
西土城 0
牡丹园 0
健德门 0
北土城 1
安贞门 0
惠新西街南口 1
芍药居 1
太阳宫 0
三元桥 1
亮马桥 0
农业展览馆 0
团结湖 0
呼家楼 1
金台夕照 0
国贸 1
双井 0
劲松 0
潘家园 0
十里河 1
分钟寺 0
成寿寺 0
宋家庄 1
石榴庄 0
大红门 0
角门东 0
角门西 1
草桥 0
纪家庙 0
首经贸 0
丰台站 0
泥洼 0
西局 1
六里桥 1
莲花桥 0
公主坟 1
西钓鱼台 0
慈寿寺 1
车道沟 0
长春桥 0
火器营 0
巴沟 0

13 16
西直门 1
大钟寺 0
知春路 1
五道口 0
上地 0
西二旗 1
龙泽 0
回龙观 0
霍营 1
立水桥 1
北苑 0
望京西 1
芍药居 1
光熙门 0
柳芳 0
东直门 1

14 26
张郭庄 0
园博园 0
大瓦窑 0
郭庄子 0
大井 0
七里庄 1
西局 1
北京南站 1
永定门外 0
景泰 0
蒲黄榆 1
方庄 0
十里河 1
北工大西门 0
九龙山 1
大望路 1
金台路 1
枣营 0
东风北桥 0
将台 0
望京南 0
阜通 0
望京 1
东湖渠 0
来广营 0
善各庄 0

15 19
俸伯 0
顺义 0
石门 0
南法信 0
后沙峪 0
花梨坎 0
国展 0
孙河 0
马泉营 0
崔各庄 0
望京 1
望京西 1
关庄 0
大屯路东 1
安立路 0
奥林匹克公园 1
北沙滩 0
六道口 0
清华东路西口 0

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值