# 地铁图快速寻路算法

1.概述

2.概念

1)点和边

2)运营段

3)代价

3.算法

1)思路

Dijkstra算法，不过这种算法没有办法解决换乘时间代价问题。

2)例子

图1(a) 时间代价　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　图1(b) 搜索顺序

{1, 2, 3, 5}
{2, 3, 4, 5}
{3, 4, 5, 6}
{4, 5, 6, 9}
{5, 6, 7, 9}
{6, 7, 8, 9}
{7, 8, 9, 10, .., ..}
{8, 9, 10, .., .., ..}
{9, 10, .., .., .., ..}
{10, .., .., .., .., ..}

3)实现

record Vertex //点
InEdges:List<Edge> //进站边
OutEdges:List<Edge> //出站边
Connection:Map<Tuple<Edge, Edge>, EdgeConnection> //边连接矩阵，包含换乘行走时间代价，当不连接时不存在

record Edge //边
Start:Vertex //起点
End:Vertex //终点
Cost:Int //乘坐时间代价
Ranges:List<Range> //运营段

record Range //运营段
Edges:List<Edge> //边
Cost:Int //等车时间

taggedunion EdgeConnection
Connected:Unit //直接连接
Transferable:Int //换乘，行走时间代价

CalculateRoute(Start:Vertex, End:Vertex):List<Edge>
if Start == End
return new List<Edge>() //起始点和终止点重合

let Previous <- new Map<Edge, Edge>() //边到上一边的映射
let cmp <- (Comparer<Edge>)(...) //路径代价比较函数，将在下面给出
let CutEdges <- new RedBlackTree<Edge>(cmp) //水流切线边列表

foreach o in Start.OutEdges
CutEdges <- CutEdges + o
Previous <- Previous + (o, null)

let e <- (Edge)(null) //终边

while CutEdges.Count > 0
let i <- CutEdges.First
CutEdges <- CutEdges - i

let s <- i.End
if s == End
e <- i
break

foreach o in s.OutEdges
if !s.Connection.ContainsKey((i, o))
continue

if Previous.ContainsKey(o)
continue

Previous <- Previous + (o, i)
CutEdges <- CutEdges + o

if e == null
return null //没有路径

let l <- new List<Edge>()
while e != null
l <- l + e
e <- Previous(e)

return l.Reverse()

let Time <- new Map<Edge, Int>()
let Range <- new Map<Edge, Range>()
let GetBestRange <- l:List<Range> => l.OrderBy(r => r.Cost).First
let GetTime <-
e =>
if e == null
return 0
if Time.ContainsKey(e)
return Time(e)
let p <- Previous(e)
let v <- GetTime(p)
if p != null
let c <- e.Start.Connection((p, e))
if c
| Connected ->
let rgOld <- Range(p)
let rg <- GetBestRange(p.Ranges.Intersect(e.Ranges))
Range <- Range + (e, rg)
if rgOld != rg
v <- v - rgOld.Cost + rg.Cost
| Transferable t ->
let rg <- GetBestRange(e.Ranges)
Range <- Range + (e, rg)
v <- v + rg.Cost + t
else
let rg <- GetBestRange(e.Ranges)
Range <- Range + (e, rg)
v <- v + rg.Cost
v <- v + e.Cost
Time <- Time + (e, v)
return v
let cmp <-
(l:Edge, r:Edge) =>
return GetTime(l) - GetTime(r)

let TransferCount <- new Map<Edge, Int>()
let GetTransferCount <-
e =>
if e == null
return 0
if TransferCount.ContainsKey(e)
return TransferCount(e)
let p <- Previous(e)
let v <- GetTransferCount(p)
if p != null
let c <- e.Start.Connection((p, e))
if c
| Connected ->
()
| Transferable _ ->
v += 1
TransferCount <- TransferCount + (e, v)
return v
let cmp <-
(l:Edge, r:Edge) =>
return GetTransferCount(l) - GetTransferCount(r)

let StopCount <- new Map<Edge, Int>()
let GetStopCount <-
e =>
if e == null
return 0
if StopCount.ContainsKey(e)
return StopCount(e)
let p <- Previous(e)
let v <- GetStopCount(p) + 1
StopCount <- StopCount + (e, v)
return v
let cmp <-
(l:Edge, r:Edge) =>
return GetStopCount(l) - GetStopCount(r)

4.算法复杂度

CutEdges的红黑树插入删除的复杂度为O(log|E|)。

5.结果

posted @ 2012-08-12 12:57 地狱门神 阅读(...) 评论(...) 编辑 收藏