C 图结构的深度复制

C 图结构的深度复制,c,C,我有一个C语言的图形结构,我想做一个深度复制(包括节点和边) 结构如下所示: struct li_list { struct li_node n; }; struct li_node { struct li_node *next, *prev; }; struct gr_graph { struct li_list nodes; int nodecount; }; struct gr_node { struct li_node node; s

我有一个C语言的图形结构,我想做一个深度复制(包括节点和边)

结构如下所示:

struct li_list {
    struct li_node n;
};

struct li_node {
    struct li_node *next, *prev;
};

struct gr_graph {
    struct li_list nodes;
    int nodecount;
};

struct gr_node {
    struct li_node node;
    struct gr_graph *graph;
    int pred_count, succ_count;
    struct li_list pred, succ;
};

struct gr_edge {
    struct li_node succ, pred;
    struct gr_node *from, *to;
    unsigned long marks;
};
struct ex_node {
    struct gr_node _; // "Superclass"
    int id;
    struct ex_node *union_find_parent;
    ...
}
这些结构本身并不存在,而是在另一个结构中“继承”,如下所示:

struct li_list {
    struct li_node n;
};

struct li_node {
    struct li_node *next, *prev;
};

struct gr_graph {
    struct li_list nodes;
    int nodecount;
};

struct gr_node {
    struct li_node node;
    struct gr_graph *graph;
    int pred_count, succ_count;
    struct li_list pred, succ;
};

struct gr_edge {
    struct li_node succ, pred;
    struct gr_node *from, *to;
    unsigned long marks;
};
struct ex_node {
    struct gr_node _; // "Superclass"
    int id;
    struct ex_node *union_find_parent;
    ...
}
是否有一个优雅的解决方案来创建这样一个结构的深度副本,包括更新对副本的引用?

注意:嵌套结构的成员不指向它所包含的根结构,而是指向它们的相关嵌套结构(例如,
ex\u节点.\uu.pred.n.next
指向
ex\u边缘.\uu.pred
)。这意味着当必须更新指针时,指针算法会非常繁琐

到目前为止,我的解决方案是

  • Memcopy所有结构
  • 遍历所有副本
  • 为包含引用的所有字段调用一组宏(由于C中缺少RTTI,我可能不会讨论这个问题)
  • 宏使用
    • offsetof
      计算根结构的地址
    • 检索复制的等效对象的地址
    • offsetof
      使指针指向正确的嵌套结构

  • 有没有更简单的方法?我还担心在添加更多字段时忘记添加宏调用。

    我认为您本身无法进行深度复制,因为指针将有一个内存地址分配给指针,所以我能想到的深度复制的最佳方法是简单地分配一个新的图形结构并复制数据(而不是指针)然后通过
    malloc
    ing新指针并调整
    ex_节点
    结构中的指针来构建它。这将是一个更彻底的解决方案

    希望这有帮助, 顺致敬意, 汤姆。听起来不错。我的$0.02:

    • 不确定为什么同时需要
      li\u列表
      li\u节点
      。此外,您不需要
      li\u节点的数据成员吗
    • 整体结构看起来有点复杂(当然,我不知道你的要求)和C++风格设计的气味(如果我错了,请原谅)
    • memcpy
      不是必需的。一个简单的任务就足够了
    • 为具有指针成员的每个结构定义函数指针成员,以便执行以下操作:
    因此:


    嵌套类型调用适当的成员复制方法…

    memcpy all struct并创建一个排序列表,其中每个条目包含原始结构的地址和结构副本的地址


    现在遍历所有副本。对于所有复制的结构中的每个指针变量,在排序列表中搜索指针,并将其替换为其副本的地址。

    是的,有一个使用生成树和装饰器模式的优雅解决方案

    -首先,构建图的生成树。您可以使用DFS(深度优先搜索) 或BFS(广度优先搜索)来实现这一点。使用decorator模式给出 每个访问的节点都有一个唯一的标识符

    -接下来,(或同时)从头到尾遍历生成树 并通过分配新节点和连接开始构建第二棵树 形成生成树的边

    -最后,再次遍历生成树,并使用 标识符,连接新图形中其余缺失的边,以便它们与 旧图的连通性。 (例如,如果图1中的节点5具有连接到节点7和节点11的边,则
    使用graph2的顺序将其节点5连接到节点7和11。)

    这比我概述的解决方案更好吗?@Meinersbur:我认为“offsetof”是计算结构成员的字节偏移量,并将字节数作为大小值返回,所以我不确定使用offsetof是否是一种方法……顺便说一下,我并不反对你的解决方案,我的答案是你正在做的事情的抽象视图…
    li#u列表
    li#u节点的“容器”
    n
    是一个哨兵列表,gr#u图来自一个库;只是我的前任。它打算以这种方式使用。这里描述了这项技术:####您的解决方案只对树有效,而不适用于图形。@Meinersbur:您的意思是循环吗?不仅仅是循环,还有DAG:引用两次的元素将被复制两次。“memcpy不是必需的”:实际上,所有的ex*都存储在一个块中。要复制数据,整个区块只是memcopy,而不是单个结构。我有一个简单得多的解决方案(这对我来说已经足够了):每个
    ex.*
    都有一个成员
    copy
    ,其中存储对副本的引用。当我有一个对原件的引用时,我也有一个对副本的引用,而不需要查找(排序)列表。对于为您定义的结构,它可以工作。但以图书馆提供的结构为例。假设您定义的结构没有直接引用它?在这种情况下,您需要将对此类结构副本的引用存储在某处。