我正在尝试用c ++写一个小quadedge类(把它想象成某种图形)。每个节点都应该跟踪他的邻居。我必须只跟踪传出的弧线。
第一个想法是使用指针来做到这一点:
struct Node {
//....
Node * n1,n2,... nk;
};
然而,当你必须实现一个复制构造函数 * 时,这种方法是特别痛苦的(首先复制所有节点,然后将指向旧节点的每个指针映射到指向新节点的相对指针) 。
我认为在这种情况下使用整数索引而不是指针会更好。
struct Node {
//....
int n1,n2,...nk;
};
这种做法是否常见且正确? 如果是,哪个是将索引映射到节点的适当容器?
std::vector<Node>
可能是最有效的方法,我可以使用向量中的索引来引用一个Node,但不幸的是从图中删除一个节点会非常复杂(需要每个都重新绑定一个节点)参考图。)
使用std::unordered_map<int,Node>
会好一点,但仍然需要跟踪自由名称(如果我插入节点1,2,3然后删除2,我需要跟踪事实名称2可用)。
我需要的是与堆的实现非常相似。考虑一个池分配器,它使用其基数的偏移作为指针类型。
是否有这样的流行容器(在Boost或任何其他流行的库中)?
*它的用处不仅限于复制构造函数,还可以考虑序列化,例如
答案 0 :(得分:1)
永久使用int
索引到容器中是非常脆弱的,因为如果不重新调整所有索引,就无法删除或插入容器中间的项目。在复制或序列化操作期间临时使用索引要好得多:使用第一种方法中描述的指针,用于不依赖于节点标识的操作,并仅创建节点的临时标识(例如,其索引)需要的操作持续时间。
例如,在复制构造函数中开始复制操作之前,请创建vector<Node*>
和unordered_map<Node*,int>
。两次执行复制:首先,添加节点的副本,不添加对向量的引用,并将旧节点的地址添加到地图中。然后再次遍历您的节点,并通过使用无序映射中的索引在向量中查找新节点的地址来解析引用。
答案 1 :(得分:0)
我认为引入这个节点ID的新概念只会让你的生活更加艰难。
如果每个节点都需要一个唯一的id用于序列化,那么在那时创建id或者只是将节点地址转换为int。
如果要复制图形,可以创建一个临时的std :: unordered_map,将旧节点映射到新节点,以跟踪已经复制的节点。
深度复制节点的函数将是递归的;它会将旧节点和新节点添加到地图中,然后深层复制尚未存在于地图中的任何邻居节点。