良好的数据结构用于表示多重图形(C)

前端之家收集整理的这篇文章主要介绍了良好的数据结构用于表示多重图形(C)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
什么是最好的数据结构描述一个无方向的多图(优化的速度和记忆)?

边缘的列表将是不合适的,因为在我的代码中经常发生顶点的邻居.

邻接列表不好,因为我必须保留关于访问边缘的信息,并且当访问1到3的边缘时(说我正在遍历1的邻居,并发现一个边缘导致三个并且具有权重w)我必须在3的邻居列表中找到相同的边缘来标记为被访问的,这是缓慢的.

我想到了每个单元格被设置为< Edge>的邻接矩阵其中Edge是表示如果访问顶点的信息的结构,边缘的权重等.然而,当访问图[0] [1] [i]时,我不能在图[1]中设置相同的边,[0]的边缘没有线性搜索.

在代表多重图形时,有什么好的方法和技巧吗?我不想要第三个图书馆解决方案,如boost :: AdjacencyList;我必须自己写.

编辑:对不起,误会了.这是大学的一个练习,我只能使用标准库来做.该图有约束:
0 < n≤300 - 顶点数
0 < m≤20000 - 边数
1≤w≤500

我的内存限制为32 MB,时间限制为0.5秒(我必须使用DFS进行访问).

解决方法

然而,提供有效的本地操作的稍微复杂的表示如下
struct Link;

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

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

基本上每个节点有两个双链表,一个用于传入链路,一个用于传出链接.每个链接知道起始和结束节点,并且还包含包含它的两个列表的prev和next指针(“from”节点中的传出列表和“to”节点中的传入列表).

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

所需的空间是每个节点和每个链路的固定数量,但是根据应用程序(每个节点有4个指针和每个链接6个指针),开销可以确定.
使用简单列表而不是双链表,开销变为每个节点2个指针,每个链接4个,但链接删除变为O(outbound_deg(from)inbound_deg(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))来分配节点的空间.

使用这种方法,节点及其输出链路的所有数据将在相邻的存储器位置.

猜你在找的C&C++相关文章