当前位置: 首页 > 知识库问答 >
问题:

表示多图的良好数据结构(C++)

竺鸿骞
2023-03-14

描述无定向多图的最佳数据结构是什么(针对速度和内存进行了优化)?

一个边的列表是不合适的,因为在我的代码中,获取顶点的邻居经常发生。

邻接列表是不好的,因为我必须保留关于已访问边的信息,并且当从1到3的边被访问时(假设我遍历1的邻居,发现一条边通向3并且具有weightw),我必须在3的邻居列表中找到相同的边以将其标记为已访问,这很慢。

当每个单元格都是时,我考虑过邻接矩阵,其中edge是表示顶点是否被访问、边的权重等信息的结构。然而,当访问图[0][1][i]时,如果不进行线性搜索,我就不能在图[1][0]的边中设置相同的边。

当表示多图时,有什么好的方法和技术吗?我不想要像boost::邻接列表这样的第三库解决方案;我得自己写。

编辑:抱歉误会。这是大学的练习,我只能用标准图书馆来做。图具有约束条件:0

我的内存限制为32 MB,时间限制为0.5秒(我必须使用DFS遍历)。

共有1个答案

龚奇逸
2023-03-14

下面是一个稍微复杂的表示,但它提供了有效的本地操作

struct Link;

struct Node
{
    Link *firstIn, *lastIn, *firstOut, *lastOut;
    ... node data ...
};

struct Link
{
    Node *from, *to;
    Link *prevInFrom, *nextInFrom, *prevInTo, *nextInTo;
    ... link data ...
};

基本上每个节点都有两个双链表,一个用于传入链接,一个用于传出链接。每个链接都知道开始和结束节点并且还具有包含它的两个列表(“From”节点中的传出列表和“To”节点中的传入列表)的prev和next指针。

使用此方法,您将获得O(1)节点和链接创建和销毁,O(inbound_deg(node))用于查找哪些链接到达节点,O(outbound_deg(node))用于查找哪些链接离开节点。该结构还支持同一对节点之间的多个连接以及多个循环。

每个节点和每个链路所需的空间是固定的,但是开销可以根据应用程序(每个节点4个指针,每个链路6个指针)而定。使用简单列表而不是双链表,开销变为每个节点2个指针,每个链接4个指针,但是链接删除变为O(outbound_deg(from)+inbound_deg(to)),并且不再是常量

还要注意,所示的结构不是缓存友好的,在现代台式计算机中,可能是一种更“暴力”的方法,例如,指针的向量而不是双链表,可以提供更好的速度,这取决于列表的大小和更改图结构的频率。

甚至可以拆分link对象来嵌入前向链接数据,例如在“From”节点中,将后向指针保留在“to”节点中。

struct Node
{
    struct OutgoingLink
    {
        Node *to;
        int incoming_index;
        ... link data ...
    };

    struct IncomingLink
    {
        Node *from;
        int outgoing_index;
    };

    std::vector<OutgoingLink> outgoing_links;
    std::vector<IncomingLink> incoming_links;

    ... node data ...
};

如果您大部分时间都在向前遍历链接,并且链接没有添加到现有节点,那么更好的做法是只为一个节点和传出的链接数据使用一个内存块,但不幸的是,C++不容易支持这一点。

在C中是

typedef struct TOutgoingLink
{
    struct TNode *to;
    int incoming_index;
    ... link data ...
} OutgoingLink;

typedef struct TIncomingLink
{
    struct TNode *from;
    int outgoing_index;
} IncomingLink;

typedef struct TNode
{
    ... node data ...
    int num_incoming_links;
    int num_outgoing_links;
    IncomingLink *incoming_links;   // separate array
    OutgoingLink outgoing_links[1]; // embedded array starting here
} Node;

使用malloc(sizeof(Node)+(num_outgoing_links-1)*sizeof(OutgoingLink))为节点分配空间。

 类似资料:
  • 问题内容: 如何用Python巧妙地表示图形?(从头开始,即没有库!)什么数据结构(例如dicts / tuples / dict(tuples))既快速又具有存储效率?一个必须能够对它执行各种图形操作。 如前所述,各种图形表示可能会有所帮助。如何在Python中实现它们?至于图书馆,这个问题有很好的答案。 问题答案: 即使这是一个有点老的问题,我还是想为遇到问题的任何人提供一个切实可行的答案。

  • 本文向大家介绍数据结构中的ADT数组表示,包括了数据结构中的ADT数组表示的使用技巧和注意事项,需要的朋友参考一下 基本概念 ADT表示抽象数据类型。 数组被定义为ADT,因为它们能够以相同的顺序保存连续的元素。他们允许 通过索引或位置访问特定元素。 它们是抽象的,因为它们可以是String,int或Person 好处 快速随机访问项目或元素。 内存效率很高,除了存储内容所需的内存很少。 缺点 元

  • 主要内容:图存储结构基本常识,图存储结构的分类我们知道,数据之间的关系有 3 种,分别是 "一对一"、"一对多" 和 "多对多",前两种关系的数据可分别用 线性表和树结构存储,本节学习存储具有"多对多"逻辑关系数据的结构—— 图存储结构。 图 1 图存储结构示意图 图 1 所示为存储 V1、V2、V3、V4 的图结构,从图中可以清楚的看出数据之间具有的"多对多"关系。例如,V1 与 V4 和 V2 建立着联系,V4 与 V1 和 V3 建立着

  • 图(graph) 图由边的集合及顶点的集合组成 有向图: 无向图: 代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Graph</title> </head> <body> <script> function Graph(v){ this.vertices=v;

  • 问题内容: 我习惯于使用PHP进行编码,但是我并不真正精通Java,这已经有一段时间了。我希望它是一个相当简单的解决方案,但是我以任何搜索方式都找不到任何好的示例代码,所以这里是: 我正在编写一个游戏,该游戏发生在基于图块的地图上的2d随机生成的无限世界中(挑剔:我知道它不是真正的无限。我只是希望世界会很大)。map [x] [y]多维数组的常用方法最初是一个基本概念,但是由于Java没有像PHP

  • 1. 类型定义 listSize(属性) 列表的元素个数 pos( 属性) 列表的当前位置 length( 属性) 返回列表中元素的个数 clear( 方法) 清空列表中的所有元素 toString( 方法) 返回列表的字符串形式 getElement( 方法) 返回当前位置的元素