城市公交查询算法的简单实现(原创)

     这几天在做一个公交乘车路线查询应用,遇到了很多人都遇到的一个问题,就是如何快速查询出直达路线、转乘路线,而不需要进行复杂的算法编程。本人在参考了CSDN上很多牛人的经验后,做出一个不用Dijkstra、弗洛伊德等算法,不需要图或邻接表等复杂数据结构,使用纯SQL存储过程的实现方法。
    首先说明,这个方法只能实现直达路线、一次转乘的查询,而且不考虑最短路径等因素。如果转乘次数超过1次,那就不得不考虑寻找其它更好的方法了。

思路:直达的情况很简单,直接可以查询出来;一次转乘时,把所有包含起始站点和到达站点的路线分拣到2张临时表中,在这两张表中查询同时包含某个换乘站点,并且该站点在起始线路中起始站点之后、到达线路中到达站点之前,这样就能查询出来了;>1次转乘,查不出来:)
以下是实现方法:
1.用表tb_kmbusstations存放所有站点的集合
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[tb_kmbusstations]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[tb_kmbusstations]
GO
CREATE TABLE [dbo].[tb_kmbusstations] (
    [idx] [int] IDENTITY (1, 1) NOT NULL ,
    [station] [nvarchar] (200) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO

insert into tb_kmbusstations(station) select '12棵橡树庄园小区'
union all select '阿拉办事处'
union all select '阿拉中学'
union all select '阿依村'
union all select '安吉路口'
union all select '安康路'
union all select '安康路口(西园路口)'
union all select '安全新村'
union all select '八公里(贵昆路)'
union all select '巴士家园'
union all select '白龙村'
union all select '白龙路(昆理工大新迎区)'
union all select '白龙路口(白云路)'
union all select '白龙寺(白龙路)'
union all select '白马'
union all select '白沙河'
union all select '白沙路口(春雨路)'
union all select '白水塘'
union all select '白水塘上村'
union all select '白水塘中村'
union all select '白塔路(银河证券)'
union all select '白塔路口(人民东路)'
union all select '白塔路口(人民东路口)'
union all select '白塔路口(世博大厦)'
union all select '白药厂'
union all select '白云路(北京路口)'
union all select '白云路(东段)'
union all select '白云路口(北京路)'
union all select '白云路西口'
union all select '百汇商场'
union all select '班庄村'
union all select '班庄村口'
union all select '宝海公园'
.................  //数据较多(900多个站点),已省略,如有需要,请联系我

2.用kmbusline存放所有公交线路
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[kmbusline]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[kmbusline]
GO
CREATE TABLE [dbo].[kmbusline] (
    [busname] [varchar] (100) COLLATE Chinese_PRC_CI_AS NOT NULL , --线路名称
    [svctime] [char] (30) COLLATE Chinese_PRC_CI_AS NULL , --开行时间
    [stoe] [varchar] (200) COLLATE Chinese_PRC_CI_AS NULL , --起始站/终到站
    [line] [varchar] (4000) COLLATE Chinese_PRC_CI_AS NULL  --线路
) ON [PRIMARY]
GO

insert into kmbusline(busname,line)
select '7路去程','潘家湾→昆师路口→昆师路口→潘家湾→市体育馆(人民西路)→红菱路(昆明肝病医院)→茭菱路口(省现代妇产科医院)→茭菱路(蕰莎堡)→西园路口(茭菱路)→丰宁小区→正大电子城→泰和园→普尔斯马特会员店→黄土坡立交桥→西部客运站→海源中路口(昆瑞路)→西山二中→三家巷→黑林铺→昆瑞路→加工厂(昆瑞路)→昭宗路口(昆瑞路)→眠山(春雨路)→七公里(春雨路)→昆明制药厂→昭宗大村(七四三四工厂)→[终到站]'
union all select '25路去程','江东花城→霖雨桥(霖雨路东)→霖雨桥(北京路口)→江东花园(江东花园北路)→江东商业街→北辰中路→北辰小区→金菊路口(金实路)→金实小区→云南茶叶市场→白云路(北京路口)→王旗营(万宏路)→万宏路(龙泉花园)→联盟路(万宏路口)→联盟路口(穿金路口)→席子营(环城东路)→昆明理工大学(新迎区)→延安医院(环城东路)→董家湾→东站(环城东路)→民航路口(环城南路)→吴井桥→北京路(环城南路口)→昆明站(北京路)→[终到站]'
union all select '25路回程','昆明站(北京路)→北京路(环城南路口)→吴井桥→民航路口(环城南路)→东站(环城东路)→董家湾→延安医院(环城东路)→昆明理工大学(新迎区)→席子营(环城东路)→联盟路口(穿金路口)→联盟路(万宏路口)→万宏路(龙泉花园)→王旗营(万宏路)→金星东门→金江路→金星西门→金夏路(北京路口)→金实小区→金菊路口(金实路)→北辰小区→北辰中路→江东商业街→江东花园(江东花园北路)→霖雨桥(霖雨路东)→江东花城→[终到站]'
union all select '26路去程','黄土坡(昆瑞路)→云南财贸学院(西区)(昆瑞路)→麻园→西园路口(工人医院)(昆瑞路)→西站→建设路(师大附中)→百汇商场→小西门(东风西路)→艺术剧院→护国桥(东风广场)→塘子巷→和平村(北京路)→北京路(环城南路口)→吴井桥→市第三人民医院→吴井路(福景花园)→吴井路口(吴井路)→五里多村→关兴路口(民航路)→云旅客运站→关上(民航路)→[终到站]'

...................... 共282条线路,其余已省略

3.存储过程
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[busSearch]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[busSearch]
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
ALTER proc busSearch
    @sta1 nvarchar(50), @sta2 nvarchar(50)
as
--所有包含起始站点的路线表
create table #tmp1(
    r_busname nvarchar(100),
    r_st char(30),
    r_stoe nvarchar(200),
    r_line nvarchar(1200)
)
--所有包含到达站点的路线表
create table #tmp2(
    r_busname nvarchar(100),
    r_st char(30),
    r_stoe nvarchar(200),
    r_line nvarchar(1200)
)

--查找结果
create table #result(
    r_bn1 nvarchar(100),
    r_st1 char(30),
    r_stoe1 nvarchar(200),
    r_line1 nvarchar(1200),
    r_station nvarchar(100), --转乘站点
    r_bn2 nvarchar(100),
    r_st2 char(30),
    r_stoe2 nvarchar(200),
    r_line2 nvarchar(1200)
)

set @sta1=@sta1+'→'
set @sta2=@sta2+'→'
--直达:
insert into #result(r_bn1,r_st1,r_stoe1,r_line1) select * from kmbusline a
    where charindex(@sta1,a.line)>0 and  charindex(@sta1,a.line)
if @@rowcount<=0 begin
--转乘:
    insert into #tmp1(r_busname,r_st,r_stoe,r_line)
    select a.busname,a.svctime,a.stoe,rtrim(a.line) from kmbusline a
        where charindex(@sta1,a.line)>0 --起始线路

    insert into #tmp2(r_busname,r_st,r_stoe,r_line)
    select a.busname,a.svctime,a.stoe,rtrim(a.line) from kmbusline a
        where charindex(@sta2,a.line)>0 --到达线路

    insert into #result
    select a.*, c.station, b.*
        from #tmp1 a, #tmp2 b, tb_kmbusstations c
        where c.station+'→'<>@sta1 and c.station+'→'<>@sta2
        and charindex(c.station+'→',a.r_line)>0 and charindex(c.station+'→',b.r_line)>0
        and charindex(@sta1,a.r_line)        and charindex(@sta2,b.r_line)>charindex(c.station+'→',b.r_line)
end
select * from #result

drop table #result
drop table #tmp1
drop table #tmp2

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

--直达:
exec busSearch '公交北市区车场',  '东风广场'

--转乘:
exec busSearch '公交北市区车场', '西坝'


在站点为928个、公交路线为282条时,测试转乘查询时间一般不超过一秒,可得到30条换乘线路。




你可能感兴趣的:(城市公交查询算法的简单实现(原创))