如何在节点类中实现节点引用

How implement node references in a node class

本文关键字:节点 实现 引用      更新时间:2023-10-16

我正在尝试用c ++编写一个小的四边类(将其视为某种图形)。每个节点都应该跟踪他的邻居。我只需要跟踪传出的弧线。

第一个想法是使用指针来做到这一点:

struct Node {
         //....
         Node * n1,n2,... nk;
};

但是,当您必须实现复制构造函数*(首先复制所有节点,然后将每个指向旧节点的指针映射到指向新节点的相对指针)时,这种方法会特别痛苦。

我认为在这种情况下使用整数索引而不是指针会是一个更好的主意。

 struct Node {
        //....
        int n1,n2,...nk;
 };

这种方法是否常见且正确?如果是,哪个是将索引映射到节点的合适容器?

std::vector<Node>可能是最有效的方法,我可以使用向量中的索引来引用节点,但不幸的是,从图形中删除节点会非常复杂(需要重新调整图形中的每个引用)。

使用 std::unordered_map<int,Node> 会好一点,但它仍然需要跟踪免费名称(如果我插入节点 1,2,3 然后删除 2,我需要跟踪名称 2 可用的事实)。

我需要的与堆的实现非常相似。考虑使用其基数偏移量作为指针类型的池分配器。

有没有像这样的流行容器(在 Boost 或任何其他流行的库中)?

*它的用处不仅限于复制构造函数,例如考虑序列化

在容器中永久使用int索引是很脆弱的,因为如果不重新洗牌所有索引,就无法删除或插入容器中间的项目。在复制或序列化操作期间临时使用索引要好得多:对于不依赖于节点标识的操作,使用您在第一种方法中描述的指针,并仅在需要的操作期间创建节点的临时标识(例如,其索引)。

例如,在复制构造函数中启动复制操作之前,请创建一个vector<Node*> 和一个unordered_map<Node*,int>。分两次执行复制:首先,添加不引用向量的节点副本,以及将旧节点的地址添加到映射中。然后再次遍历节点,并使用无序映射中的索引在向量中查找新节点的地址来解决引用。

我认为引入节点ID的这个新概念只会让你的生活更加艰难。

如果需要每个节点的唯一 ID 进行序列化,请在此时创建 id,或者只是将节点地址转换为 int。

如果要复制图形,可以创建一个临时 std::unordered_map,将旧节点映射到新节点,以跟踪哪些节点已被复制。

然后,用于深度复制节点的函数将是递归的; 它会将旧节点和新节点添加到映射中,然后深层复制映射中尚未存在的任何相邻节点。