路网的存储

一、选择合适路网存储结构的必要性

道路网络的存储方法不但对路径优化算法的性能有重要影响,而且是车辆定位、地图匹配以及路径引导的基础。在图论中诸如Dijkstra、A*等经典的路径优化算法,在实际应用时实时性较差,主要原因有:

  • 1)路网是有向图
  • 2)道路交叉口与图论中节点不同,它本身有权重且常常不唯一
  • 3)路网中存在各种转向限制
    因此需要使用合适的路网存储结构提高算法效率。

二、图的分类

  • 有向图、无向图

  • 带权图、不带权图

三、路网内存中的存储机制

下面介绍的是图在内存中存储的数据结构。尝试用以下3种方法存储下图(把它看做一个双向连通的有向图,括号中为节点编号),无向图是特殊的有向图自然也可以用以下方法进行存储。

1.邻接矩阵(顺序存储)

G=(V,E)是具有n个节点的图,顶点序号依次为0,1,...,n-1,则G的邻接矩阵是具有如下定义的n阶方阵A:

A[i][j]=0表示顶点i与顶点j邻接,即i与j之间存在边或者弧;
A[i][j]=1表示顶点i与顶点j不邻接
(0<=i,j<=n-1)

1)代码

public class MGraph {
    // 图的节点
    class Node {
        // 节点编号
        int num;
        // 节点属性
        char info;
    }

    // 节点
    Node[] nodes;
    // 边
    double[][] edges;
    // 节点个数
    int n;
    // 边个数
    int e;

}

2)图示

nodes数组


邻接矩阵


3)评价

实际路网是大型稀疏图,不建议采用

2.邻接表(链式存储)

1)代码

public class AGraph {
    class ArcNode {
        // 该边指向的节点
        int num;
        // ...其他信息
        // 下一指针域
        ArcNode next;
    }
    class Node {
        // 节点编号
        int num;
        // 信息
        char info;
        // 从节点num出发的边存在后面的链表中
        ArcNode nextArc;
    }
    // 节点
    Node[] nodes;
    // 节点数
    int n;
    // 边数
    int e;
}

2)图示

3)评价

常用于稀疏图,节省存储空间

3.前向关联边

Dial于1979年提出。道路网络是大型稀疏网络,具有转向限制、节点带权重等特点

前向关联边结构中主要有三个数组,

  • 一个用来存储与弧有关的数据
  • 另一个用来存储与节点有关的数据
  • 将每个节点的所有邻接节点按顺序存储在数组中一块连续的空间中,并记录每一个节点在所指向的节点数组中第一次出现的位置和邻接节点个数总和。

1)代码

public class MyGraph {
    // 节点个数
    public int n;
    // 边个数
    public int e;
    // 结点集合
    public Node[] nodes;
    // 所有节点发出的所有边(按照特定的顺序排列起来)
    public int[] linkedEdges;
    // 边集合
    public Edge[] edges;

    public MyGraph() {}


    public MyGraph(int n, int e) {
        this.n = n;
        this.e = e;
        // 从数组下标0开始存储
        nodes = new Node[n];
        edges = new Edge[e];
        linkedEdges = new int[e];
    }

    public static class Node implements Comparable < Node > {
        // 节点编号
        public int nodeId;

        // 节点名称
        public String nodeName;

        // 经度
        public float longtitude;

        // 纬度
        public float latitude;

        // TODO: 2018/10/30  节点类型
        public int type;

        // 是否有红绿灯
        public boolean hasLed;

        // 从该节点发出的弧个数
        public int count;

        // 该节点发出的第一个弧在linkEdges中的下标
        public int linkEdgesBeginIndex;

        // 该节点处的转向限制
        public List < ForbiddenTurn > forbiddenTurnList;

        // 该节点数据是否为手动采集
        public boolean fromManual;

        public Node() {}

        public Node(int nodeId) {
            this.nodeId = nodeId;
        }



        // 定义默认访问规则
        @Override
        public int compareTo(Node o) {
            return this.nodeId - o.nodeId;
        }
    }

    public static class Edge {
        // 路段编号
        public int edgeId;

        // 路段名称
        public String edgeName;

        // 道路长度
        public double length;

        // 道路宽度
        public double width;

        // 车道数
        public int laneNum;

        //         道路等级:高速公路、国道、省道、县道、乡道、城市快速路等

        // 开始节点编号
        public Node enterNode;

        // 结束节点编号
        public Node exitNode;

        // TODO: 2018/10/30 路段属性

        // TODO: 2018/10/30 路段权值
        // 路段权值
        public double weight;

        // 该道路是否连通
        public boolean isConnected;

        // 是否为手动采集
        public boolean fromManual;


    }

    public static class ForbiddenTurn {
        // 结点编号
        public int nodeId;
        // 进节点编号
        public int enterNodeId;
        // 出节点编号
        public int exitNodeId;

        public ForbiddenTurn() {}

    }
}

2)图示

将nodes数组按照节点编号从小到大排序(为了后面根据节点编号查找节点时可使用二分查找)

为了表达禁行关系,需要把每个节点的禁行关系单独进行存储。为每个节点添加一个标志信息,该标志信息提示该节点处有没有转向限制,同时将转向禁止的进入节点出去节点存储起来(下图中需存储节点A的禁行关系,进入节点是B,出去节点是C),当路径规划扩展到节点A时,如果下一步扩展的节点是C,则需要检查进入的节点是否是节点B,如果是的话扩展失败(因为此交叉路口时此方向转向禁止)

3)评价

路网作为大型稀疏网络,该存储方式可节省存储空间,并表达交叉口转向限制。

参考文献

导航路径规划之二 路网的存储结构

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容