从std::vector中删除元素后更新存储的索引
Updating stored indices after erasing an element from std::vector
假设我有一个点向量:
vector<int> points;
三角形存储组成它们的点的索引:
struct Triangle {
int p0, p1, p2;
};
Triangle tri0;
tri0.p0 = 3;
tri0.p1 = 6;
tri0.p2 = 7;
Triangle tri1;
tri1.p0 = 4;
tri1.p1 = 6;
tri1.p2 = 7;
现在我决定擦除point[3]
。然而,如果我擦除point[3]
,索引3之后的点的索引将移回,所以我需要通知所有三角形它们存储的索引可能会改变。通知三角形的合理方式是什么?
在我看来,最合理的方法是而不是删除顶点。因为如果你真的删除它们,那么你必须将所有的顶点向右移动(平均V/2元素),然后你必须遍历所有的三角形(T总是检查)。
相反,您可以将顶点标记为dead。简单地把一些坏值点数组(在你的样本-1
是ok的)。在每次删除中添加标记只需要O(1)。有时,您可能想要物理地移除死顶点。你可以用两个完整的通道(一个顶点,一个三角形),并在线性时间O(V + T)压缩你的网格。
为了使事情易于使用,我建议为你的网格创建一个类。在网格对象中,对类用户透明地维护失效条目的数量。当删除后死条目的部分变得相当大(例如超过一半)时,调用死顶点消除。您还可以创建三角形枚举方法,它只会在活动三角形上迭代(只是为了方便)。
此方法确保O(1)每次删除的平摊时间,如果花费在压缩上的时间不大于删除次数乘以常数。给定T <= c V在任意时刻(对于某常数c),它为真。实际上,不太可能看到三角形数量大于顶点数量的网格,所以你很好。
一个非常不同的解决方案是使用链表而不是数组来存储顶点和三角形(彼此有指针)。在这种情况下,你可以在O(Sv)时间内移除顶点v,其中Sv是它所属的三角形数。但是这种数据结构的底层性能可能很差。
编辑:另一个问题出现在我的脑海里。死顶点消除对用户来说是透明的,但此时用户可能会陷入三角形或顶点枚举的中间。显然,这种情况会造成很大的麻烦。
为了避免危险,在你的网格中添加lock
/unlock
方法。这样你就可以确保只要一个网格被锁定,它的顶点就会保持在索引方向上。在这种情况下,您可以安全地执行顶点过滤之类的操作,例如
相关文章:
- 从C++本机插件更新Vector3数组
- 将字符串存储在c++中的稳定内存中
- QGraphicsPolygonItem在拖动时未更新QPolygonF坐标
- std::原子加载和存储都需要吗
- C++:将控制台输出存储在宏中更好吗
- 使用QProcess执行命令,并将结果存储在QStringList中
- 访问存储在向量C++中的结构的多态成员
- 如何从存储在std::映射中的std::集中删除元素
- cmake更新缓存的变量
- 存储模板类型以强制转换回派生<T>
- 类型总是使用其大小存储在内存中吗
- 当字符串存储在变量中时,如何将字符串转换为wchar_t
- 更新存储在地图中的向量的向量
- 存储将经常更新的大数组的正确结构是什么
- 对"检查更新"按钮进行编程以确定存储库中的更改
- 通过类存储和更新矢量中的电流最小值
- Qt模型视图:当数据存储和更改数据时,更新模型和视图的正确方法是什么::vector
- 如何存储变量的前一个值并更新它以进行比较
- 存储数据和访问,并在C++中执行后从内存中更新
- 从std::vector中删除元素后更新存储的索引