搞了一天公交轉乘演算法,最近想做個公交app(sench touc),先把人家思路弄這裡。。。

來源:互聯網
上載者:User

三個表(最簡單化,不考慮模糊查詢,單行線等其他東西):
1,網站表stop(stop_id,stop_name)
2,路線表line(line_id,line_name)
3,路線網站表(點線路關係表)linestops( line_id, stop_id, seq )此處的seq指某網站在某線路中的順序。

現在分析演算法:
1,直達線路
首先根據兩個網站名擷取兩個網站各自的id,這裡定義為id1,id2
然後查詢
select line_id from
(select line_id from linestops where stop_id = id1) A,
(select line_id from linestops where stop_id = id2) B
where A.line_id = B.line_id
即得到可直達的線路列表
2,一次轉乘
首先根據兩個網站名擷取兩個網站各自的id,這裡定義為id1,id2
然後搜尋兩個網站通過直達方式各自能夠到達的網站集合,最後他們的交集就是我們所需要的轉乘網站。
select stop_id from
(
select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id1)
)A,
(
select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id1)
)B
where A.stop_id= B.stop_id
得到轉乘站(可能有多個或0個)後,剩下的就是顯示能夠到達轉乘站的兩邊線路,這通過前面的直達查詢即可。
3,二次轉乘
首先根據兩個網站名擷取兩個網站各自的id,這裡定義為id1,id2
演算法的中心思想是:網站1能夠通過直達到達的所有網站集合A,網站2能夠通過直達到達的所有網站集合B,A和B之間有直達的線路。
一步一步來:
網站1能夠通過直達到達的所有網站集合A:
select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id1)
網站2能夠通過直達到達的所有網站集合B:
select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id2)
而直達的查詢是
select line_id from
(select line_id from linestops where stop_id = id1) C,
(select line_id from linestops where stop_id = id2) D
where C.line_id = D.line_id
我們把=id1和=id2換成 in (select ....)A 和 in (select ...)B
這樣最後我們的查詢是
select line_id from
(select distinct line_id from linestops where stop_id in 【A】) C,
(select distinct line_id from linestops where stop_id in 【B】) D
where C.line_id = D.line_id
其中【A】是
(select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id1))
其中【B】是
(select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id2))
這樣子我們找到了作為中間轉乘的線路(可能有多條或者0條),對列舉的的每一條假設命名為X線,下一步就是找出可以從網站1到達X任意一個網站的直達線路、和可以從網站2到達X任意一個網站的直達線路即可。
那麼與前面的演算法相似,我們在網站1所有能夠到達的網站中去尋找和線路X相交的網站,然後再去找這兩個點的線路
select stop_id from
(select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id1))A,
(select stop_id from linestops where line_id = X ) B
where A.stop_id = B.stop_id
找到網站了,下面就是根據已經解決的直達查詢找線路了。
網站2類似。
以上的演算法有一個優點,全部是sql完成搜尋,所以asp代碼只需寥寥幾行迴圈而已。
但是缺點是:慢,畢竟可能涉及了數百次sql查詢。而且只是用最簡單的sql方法去算出所有可以轉乘的方案,不涉及最優/最短的演算法。如果是最短路徑,那得用特殊結構和演算法。

另外:

根據出行者輸入的起點和終點,確定出行要選擇的起始公交網站A和目的公交網站B。搜尋資料庫,查詢網站A和網站B之間是否有相同的車經過,如果有一條或幾條直達線路,通過比較選擇距離最短的公交線路推薦給出行者。如果沒有,則計算網站A和網站B之間有沒有一個公用網站C,從網站C可以轉乘到達網站B。這就有兩種情況:(1)如果有,屬於一次轉乘。計算網站A和公用網站C之間有沒有相同的公交車經過並存入集合X;同樣,計算網站B和公用網站C之間有沒有相同的公交車經過並存入集合Y。將這兩個集合比較後就可以得到從網站A經過公用網站C到達網站B的公交線路,在這些線路中進行比較,選擇距離最短的推薦給出行者。(2)如果沒有公用網站C,就出現了要轉乘兩次的情況。將經過網站A的每條公交線路的所有網站存入集合O;同樣,經過網站B的每條線路的所有網站存入集合P。比較這兩個集合,先乘經過網站A的某一路車到達某一網站D,計算網站D與網站B之間有沒有公用網站E,如果有則網站D、E為轉乘網站。這種方案可能有多種,比較選擇距離最短的推薦給出行者。如果不存在公用網站E,說明經過兩次轉乘無法從網站A到達網站B,停止搜尋計算。
公交出行最優路線具體演算法:
1) 輸入起始網站A和目的網站B;
2) 搜尋系統資料庫,經過起始網站A的公交線路存為X(i)(i=1,2,3…,m,m為正整數),經過目的網站B的公交線路存為Y(j)(j=1,2,3,…n,.n為正整數);
3) 判斷是否有X(i)=Y(j),將滿足條件的存入Z。若Z=1,則該條公交線路X(i)即Y(j)為從網站A到網站B的直達最優線路,輸出結果並結束運算。Z≥1,計算Z中各條線路的距離,選擇一條距離最短的線路,輸出結果並結束運算;
4) 搜尋系統資料庫,公交線路X(i)所包含的網站存為O(i,u)(u=1,2,3…,g,g為正整數)公交線路Y(j)所包含的網站存為P(j,v)(v=1,2,3…,h,h為正整數);
5) 判斷是否有O(i,u)= P(j,v),將滿足條件的存入W。若W=1,則網站O(i,u)即P(j,v)為從網站A到網站B的一次轉乘網站,公交線路X(i),Y(j)為轉乘一次的最優路線,輸出結果並結束運算。若W≥1,分別計算每條轉乘路線的距離,選擇一條距離最短的線路,輸出結果並結束運算;
6) 搜尋系統資料庫,經過網站O(i,u)的公交線路存為R(k)(k=1,2,3…,p,p為正整數),公交線路R(k)所包含的網站存為G(k,t)(t=1,2,3…,q,q為正整數);
7)判斷是否有G(k,t)=P(j,v),將滿足條件的存入S。若S=1,則網站G(k,t)即P(j,v)為從網站A到網站B的二次轉乘網站,公交線路X (i),R(k),Y(j)為轉乘二次的最優路線,輸出結果並結束運算。若S≥1,分別計算每條轉乘二次的路線距離,選擇一條距離最短的線路,輸出結果並結束運算;
8) 以上步驟沒有找到合適的公交線路,輸出“沒有找到轉乘次數不超過兩次的最優公交線路”,結束運算。
本文討論的公交出行最優路線演算法,主要是以距離為標準。在得出了轉乘方案之後,可以進一步考慮時間因素,從而找到更具優勝性的轉乘方案,這有待進行進一步的探討、研究。

一、公交轉乘問題的演算法分為兩個步驟:

1、構造並求解轉乘矩陣,獲得公交轉乘方案(即從起點到終點最少轉乘次數,及轉乘網站)。
有三種實現形式:
①、求得所有節點T矩陣,兩個節點直達設為1,兩個節點不通或需要轉乘設為0;參見《公用交通系統最佳路徑演算法》
②求得所有線路的T矩陣,兩條線路相交設為1,兩個線路不相交設為0;參見《基於鄰接矩陣的公交轉乘演算法的研究》(注該演算法屬於理想化演算法)
③通過上述第2個步驟縮小範圍,然後用第一個步驟求得精確結果

2、根據最少轉乘次數,縮小求解範圍,求解起始網站與目標網站間的最短路徑,進而得到最佳路徑。
最短路徑獲得有以下幾種形式:
①、最簡單的實現方法:如果上面1的最少轉乘次數、轉乘網站都能求解出來,只需要查詢轉乘次數最少的情況下,所有可能的路徑中網站數最少的線路即為所求(前提,假設所有網站之間的距離大致相等);
②、如果上面1隻求出來最少轉乘次數,這時需要用演算法求最短路徑,常用的方法是改進Dijkstra演算法,也就是在Diskstra演算法中增加了一條判斷最少轉乘演算法的一項;
③、在遊戲設計程式中,經常要涉及到最短路徑的上述,最常採用的演算法是A*演算法,參見《遊戲地圖最短路徑搜尋設計與實現》和《A演算法》
④、K(<=3)條漸次短路徑搜尋演算法,這種演算法國外用的比較多,由於該演算法比較麻煩,國內研究不太多,參見《K(≤3)條漸次短路徑搜尋演算法的研究》、《一種新的Kth最短路徑搜尋演算法》和《城市軌道交通轉乘票務清分模型的研究》(碩士論文)
⑤、螞蟻演算法,參見《一種仿Dijkstra的螞蟻演算法》
其中,②③④⑤步驟中都需要依靠最少轉乘次數來達到降低複雜度的目的。

二、上述演算法如能得到很好的實現,需要建立一個好的資料結構

1、資料存放區形式
我曾問過兩個實際搞過這方面的人,一個人採用數組來儲存,另外一個所採用鏈表與數組相結合的方式(即長鏈表採用數組,其它採用鏈表的方式),其實,之所以有上述兩個儲存形式,主要是因為這兩個人演算法中側重面不同,前一個側重實現最少轉乘次數,後一個則側重最短路徑的實現。
2、資料結構儲存,可參考《城市公交網路出行直接選取的電腦演算法研究》、《基於GIS的標準公交基礎資訊系統》《基於GIS的公交乘客出行直接選取模型》,考慮到公交轉乘,所以通常情況下,把相近的網站(網站名一樣但地理位置不同的、網站名不一樣但地理位置很接近的)作為公交網路拓撲結構中一個節點。
3、兩個節點之間弧段權值的選取(計算最短路徑需要):通常情況下,用兩個節點之間的距離代替,但也有人用公交車在這兩個節點之間的速度或行車時間來作為權值。是瀋陽公交網給出來的環路車參數,根據該參數和兩個網站之間的距離可以求出網站之間的行車時間(正常)。當然因素考慮的越齊全,越人性化,但是程式上就增加了很多難度, 比如:考慮“等車時間、網站距離、線路的熱度(通往商業區)、時間(上班高峰期等)”等因素,這些因素都很難量化,所以,通常情況下,最簡單的方法用距離來作為兩個節點之間弧段的權值。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.