最初是做2004年某期《程序员》杂志上的一道题,叫“洞穴探险”,结果写着写着就做到公交换乘的思路上去了。看来做GIS做久了,都成习惯了。后来工作忙,就扔下了。最近翻看以前自娱自乐时写的东东,看到了这段代码,索性贴出来共享,抛砖引玉吧。

文中使用的queue_alloc和queue_free函数是洒家自己设计的“简易空间配置器”的C 语言实现版本,关于简易空间配置器的详细信息,请参考《简易空间配置器》(http://blog.csdn.net/bfbd/archive/2004/06/22/22743.aspx)一文。

#include "stdafx.h"

#include

#include

#include

using namespace std;

const _BUF_SIZE_ = 100;

// C版本的搜索函数

extern "C"

{

typedef struct Q_NODE

{

int id;    //节点编码

Q_NODE *father;  //父节点的地址

} Q_NODE;

/*

队列由多段缓冲区组成,每段缓冲区为连续的多个节点。

id大于0时表示节点的编码值。

father为正常的内存地址时表示本节点的父节点所在的内存

id为0表示当前节点为缓冲区末尾节点,其father指向下一个缓冲区段的起点。

father为空表示当前节点为队列末尾节点

father为-1表示当前节点为树的根节点

*/

void dumpMap(int n, int *ph, int *pl)

{

int _i;

printf("ph[]: ");

for (_i=0; _i

printf("%d ", ph[_i]);

printf("\n");

printf("pl[]: ");

for (_i=0; _i

printf("%d ", pl[_i]);

printf("\n");

}

void dumpDeep(int n, int *pd)

{

int _i;

printf("pd[]: ");

for (_i=0; _i

printf("%d ", pd[_i]);

printf("\n");

}

void dumpQueue(Q_NODE *Qs)

{

Q_NODE *_pQ;

printf("Q: ");

for ( _pQ=Qs; (_pQ->father && _pQ->id); _pQ++ )

{

printf("%d->%d ", _pQ->id,

((-1!=(int)_pQ->father) && (_pQ->father)) ? (_pQ->father->id) : 0);

if ( 0==_pQ->id )

_pQ = _pQ->father;

}

printf("\n");

}

Q_NODE* queue_alloc(int size)

// 为队列申请新的空间

// size: 申请的空间大小

// return: 申请空间的起始地址

{

Q_NODE *Qb = new Q_NODE[size];

//初始化对列缓冲区

memset(Qb, 0, sizeof(Q_NODE) * size);

for (int i = 0; i < size - 1; i++)

Qb[i].father = &(Qb[i+1]);

Qb[size-1].father = NULL;

return Qb;

}

void queue_free(Q_NODE* pQ, int size)

// 释放对列所占的内存

// pQ: 队列起始地址

// return:

{

if (NULL != pQ)

{

Q_NODE* p;

while (NULL != pQ)

{

p = pQ;

pQ = pQ[size-1].father;

delete[] p;

}

}

}

void search_change(int n, int *ph, int *pl, int *pd)

// 搜索换乘路径

// n: 节点个数

// *ph: 邻接压缩表描述序列(长度为n+1)

// *pl: 邻接压缩表序列(长度为ph[n])

// *pd: 换乘深度(长度为n+1,pd[0]不用),0 表示未达站点,1 表示出发站,-1 表示终点站。

// return:

{

#ifdef _DEBUG

dumpMap(n, ph, pl);

dumpDeep(n, pd);

#endif //_DEBUG

assert(n > 2);

int i; //循环计数器

Q_NODE *Qs,  //队列头部

*Qe, //队列尾部

*pQ1, //队列元素指示器

*pQ2;

Qs = Qe = queue_alloc(_BUF_SIZE_);

//出发节点加入队列

for (i = 1; i < n + 1; i++)

{

if (1 == pd[i])

{

if (NULL == Qe->father)

{

Qe->id = 0;

Qe->father = queue_alloc(_BUF_SIZE_); //扩充队列

Qe = Qe->father; //跳过缓冲区末尾的节点

/*

缓冲区末尾的节点id为0(一个不可能出现的节点编码),

表示本节点的father指针指向下一个缓冲区的起始地址,

而不是本节点的父节点地址。

*/

}

pQ2 = Qe->father;

Qe->id = i;

Qe->father = (Q_NODE *)-1; //一个不可能出现的内存空间地址,但不可用NULL

Qe = pQ2;

}

}

#ifdef _DEBUG

dumpQueue(Qs);

dumpDeep(n, pd);

#endif //_DEBUG

//路径搜索

int w, //父节点的id

u; //子节点的id

pQ1 = Qs;

// 利用队列进行层级遍历

while (Qe != pQ1)

{

if ( 0 == pQ1->id )

pQ1 = pQ1->father;

w = pQ1->id;

// 遍历w的子节点

for (i = ph[w-1]; i < ph[w]; i++)

{

u = pl[i];

if (-1 == pd[u]) // 找到换乘通路

{

// ... 输出换乘通路

printf("(%d)", pd[w]);

printf("%d", u);

Q_NODE *path = pQ1;

while ((Q_NODE *)-1 != path)

{

printf(" - %d", path->id);

path = path->father;

}

printf("\n");

}

else if (0 == pd[u]     //未到达节点

|| pd[w] + 1 == pd[u] )  //已达,但属同一层

{

if (NULL == Qe->father) //扩充队列

{

Qe->id = 0;

Qe->father = queue_alloc(_BUF_SIZE_);

Qe = Qe->father; //跳过缓冲区末尾的节点

}

//添加节点

pQ2 = Qe->father;

Qe->id = u;

Qe->father = pQ1;

Qe = pQ2;

//标记换乘深度

pd[u] = pd[w] + 1;

}

}

#ifdef _DEBUG

dumpQueue(Qs);

dumpDeep(n, pd);

#endif //_DEBUG

//步进到下一节点

pQ1++;

}

//释放队列

queue_free(Qs, _BUF_SIZE_);

}

int main(int argc, char* argv[])

{

// 打开输入文件

FILE *in;

if (argc < 2)

in = fopen("Input.txt", "r");

else

in = fopen(argv[1], "r");

if (NULL == in)

{

fprintf(stderr, "Cannot open input file.\n");

return 1;

}

// 读取输入文件到邻接压缩表中

int num_node;

vector h; //邻接压缩表描述序列

vector l; //邻接压缩表序列,即可直达站点列表

vector mark; //节点到达标记序列

if (fscanf(in, "%d\n", &num_node))

{

assert(num_node>2);

h.resize(num_node+1);

h[0] = 0;

for (int i=0; i

{

int num_arrival;

fscanf(in, "%d", &num_arrival);

assert(num_arrival>0);

h[i+1] = num_arrival + h[i];

l.resize(h[i+1]);

for (int j=h[i]; j

{

int id_node;

fscanf(in, "%d", &id_node);

l[j] = id_node-1;

}

}

}

// 关闭输入文件

fclose(in);

// 调用函数搜索可行路径

{

int n = h.size() - 1;

int *ph = new int[h.size()];

int *pl = new int[l.size()];

copy(h.begin(), h.end(), ph);

copy(l.begin(), l.end(), pl);

for (int i=0; i

pl[i] = pl[i] + 1;

//  search_change(n, ph, pl, 1, 10);

//  search_change(n, ph, pl, 5, 10);

printf("\n");

int *pd = new int[h.size()];

memset(pd, 0, h.size() * 4);

pd[1] = 1;

pd[5] = 1;

pd[10] = -1;

search_change(n, ph, pl, pd);

delete[] pd;

delete[] ph;

delete[] pl;

}

// 搜索可行路径

int n_start = 0; //出发节点

int n_end = 11;  //目的节点

// 打开输出文件

FILE *out;

out = fopen("./Output.txt", "w+");

// 算法

{

mark.resize(h.size()-1);

{for (int i=0; i

vector< pair > Q; //队列,存储路径搜索树,记录节点序号和父节点在本队列中的位置

mark[n_start] = 0;

Q.push_back(make_pair(n_start,-1));

for (int i=0; i

{

int w = Q[i].first;

// 遍历w的直达节点

for (int j=h[w]; j

{

int u = l[j];

if (u == n_end) { //存在换乘通路

// 输出换乘通路

//利用w的父节点在队列中的位置进行上溯,找到换乘路径

fprintf(out, "%d: %d,%d,%d,%d,%d\n",

mark[w] + 1, u,w,Q[Q[i].second].first);

//Q[Q[Q[i].second].second].first,Q[Q[Q[Q[i].second].second].second].first);

}

else if (mark[u] == -1) { //未到达节点

Q.push_back(make_pair(u,i)); //子节点入栈并记录其父节点在队列中的位置

mark[u] = mark[w] + 1; //记录当前换乘深度

}

else if (mark[u] == mark[w] + 1) {

Q.push_back(make_pair(u,i));

}

}

}

}

// 测试输入部分的正确性

#ifdef _DEBUG

{

assert( out != NULL );

fprintf(out, "%d\n", h.size()-1);

for (int i=0; i

{

fprintf(out, "(%d) ", i + 1);

for (int j=h[i]; j

fprintf(out, "%d ", l[j] + 1);

fprintf(out, "\n");

}

}

#endif

// 关闭输出文件

fclose(out);

return 0;

}

} // extern "C"

《Input.txt》

12

4 3 4 2 5

2 8 1

2 9 7

2 6 11

3 8 2 3

2 9 10

2 10 11

1 12

2 10 12

1 12

1 12

2 5 8

《output.txt》

3: 11,8,2,0,0

3: 11,10,3,0,0

3: 11,7,1,0,0

3: 11,7,4,0,0

4: 11,9,8,0,0

4: 11,9,6,0,0

4: 11,9,5,0,0

公交换乘系统c语言,公交换乘的简单实现(源码)相关推荐

  1. 基于Android公交查询系统的设计与实现(论文+程序设计源码+数据库文件)

    [摘 要]随着互联网的技术的不断更新发展,人们生活节奏也在不断的加快,对于网络的依赖也越来越紧密,尤其是在等公交,经常会错过班次,但又不知道,下次班次几点发车,这样会导致乘客花掉大把时间在等待,如果可 ...

  2. 基于B/S的城市公交查询系统的设计与实现(附:源码+论文+答辩PPT))

    摘  要 近年来, Internet推动了以互联网技术为核心的各项工作蓬勃展开,互联网的强大也大大的促进了社会的发展,整个社会信息化进程逐步加快,网络也变成了我们日常活动中越来越重要的组成成分.为了使 ...

  3. uniapp盲盒商城交易平台系统多语言国外H5盲盒商城源码

    这是uniapp全开源盲盒商城交易平台系统二次开发带易码支付通霸云H5盲盒商城源码. 这个盲盒系统对接的短信宝,码支付易支付,微信登录,阿里云OSS,后台有盲盒商品抽奖概率设置,可设置落地域名(炮灰域 ...

  4. 多语言跨境电商商城源码系统平台

    多语言跨境电商商城源码系统平台是一款集成手机端.PC端和小程序端等多端口的跨境电商平台 具有以下主要功能: 多语言支持:支持多种语言切换,可以满足不同国家用户的需求. 商品管理:提供商品分类.商品列表 ...

  5. C语言成绩统计源代码,C语言课程设计学生成绩管理系统+源码

    <C语言课程设计学生成绩管理系统+源码>由会员分享,可在线阅读,更多相关<C语言课程设计学生成绩管理系统+源码(25页珍藏版)>请在人人文库网上搜索. 1.简易教学管理系统的设 ...

  6. 医院管理住院系统的研究与实现(论文+PPT+源码)

    医院管理住院系统的研究与实现 摘要 医院管理住院系统是一项集多类学科为一体的系统,其中包含医学.信息.计算机等学科,广泛的应用在当今欧美等发达国家,给治疗患者们提供了很大的便利.假如全面实现了这一系统 ...

  7. ​​​​Java毕设项目智慧公寓系统演示录屏2021计算机(附源码+系统+数据库+LW)

    Java毕设项目智慧公寓系统演示录屏2021计算机(附源码+系统+数据库+LW) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也 ...

  8. JAVA计算机毕业设计蛋糕店会员系统的设计与实现计算机(附源码、数据库)

    JAVA计算机毕业设计蛋糕店会员系统的设计与实现计算机(附源码.数据库) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ ...

  9. Java毕设项目蛋糕店会员系统的设计与实现计算机(附源码+系统+数据库+LW)

    Java毕设项目蛋糕店会员系统的设计与实现计算机(附源码+系统+数据库+LW) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行 ...

最新文章

  1. 从零开始MDT2010学习手记(二) 创建共享工作目录
  2. 7445 oracle,Oracle 10g impdp 报 ORA-7445 [_INTEL_FAST_MEMCPY.A] 解决方法
  3. 6 rethad 自定义硬盘_图文详解zabbix配置自定义监控项过程
  4. [算法]复杂链表的复制
  5. java 试卷自动生成_基于JAVA的试题自动生成系统 - WEB源码|JSP源码/Java|源代码 - 源码中国...
  6. github-新建文件夹
  7. 【LA 2572】Viva Confetti(圆与圆弧覆盖+精度问题)
  8. 【14年浙江省赛 F ZOJ 3781】Paint the Grid Reloaded 【建图、bfs】
  9. Python实现贷款用户的信用评分卡
  10. 关于触摸屏触摸驱动安装步骤
  11. 大数据算法-重复率计算 ICardinality
  12. C语言根据汉字拼音首字母排序
  13. Ubuntu添加Pycharm的快捷方式
  14. js实现刷新页面的方法
  15. 2.基于Spring-Boot的代码规范实例
  16. html怎么取消转义字符,正确取消html字符的转义
  17. iOS---修改Xcode7建立的工程名称
  18. python做生日祝福短信_祝福短信之整蛊生日祝福语
  19. Java学习---第三周周报
  20. echarts K线图candlestick

热门文章

  1. LeetCode 1368. 使网格图至少有一条有效路径的最小代价(BFS最短路径,难)
  2. POJ 1007 DNA排序解题
  3. yolov2训练_一文看懂YOLO v2
  4. css样式子绝父相,子绝父相_HTML+CSS前端基础知识教程_腾讯视频
  5. c语言程序做成可执行文件,windows环境下C程序生成可执行文件
  6. oracle聚合函数wmsys,oracle 自定义聚合函数
  7. MYSQL中有时候不得不使用replace()去掉特殊字符,写在这里备用一下
  8. tkinter的可视化拖拽工具_可视化越做越丑?这五个高级图表效果实现流程分享给你...
  9. 卖萌屋学术站开放注册啦!寻募种子用户,超多特权放出!
  10. 高并发编程系列:NIO、BIO、AIO的区别,及NIO的应用和框架选型