日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

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

發布時間:2024/7/19 windows 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 公交换乘系统c语言,公交换乘的简单实现(源码) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最初是做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语言,公交换乘的简单实现(源码)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。