我正在使用STL std :: multiset<>作为指针的排序列表。排序顺序由所指向项目的属性决定,这与本简化示例相似:
struct A
{
int x;
};
bool CompareAPointers(const A* lhs, const A* rhs)
{ return lhs->x < rhs->x; }
std::multiset<A*, CompareAPointers> sorted_set;
复杂的是,用于对集合进行排序的属性值可能会发生变化(您可以在上面的示例中更改A.x),这可能会使排序顺序不正确:
A a1, a2;
a1.x = 1;
a2.x = 2;
sorted_set.insert(&a1);
sorted_set.insert(&a2);
a1.x = 3;
当相关属性发生变化时,我可以通过擦除和重新插入元素来保持列表排序,但是簿记会变得有点痛苦。我觉得我这一切都错了。任何人都可以建议一种更好的方法来保持列表排序时排序顺序可以动态更改?这些变化在可预测的时间以可预测的方式发生,但我当前的方法感觉错误。
答案 0 :(得分:6)
Boost Multi-Index支持对您想要的任何内容进行排序,并支持更改列表获取的字段,但您不能再仅仅键入a1.x=1
,而是必须使用MultiIndex::replace()。
我无法想到更快/更自然的方式,因为删除和重新插入元素无论如何都要完成。
答案 1 :(得分:1)
我会考虑使用排序std::vector
代替。在其中一个点,您可以预测为其中一个成员修改x
,然后只需对向量进行重新排序。它比移除和重新插入项目更清洁。如果您经常修改单个集合成员的属性并重新排序,这可能会带来太大的开销。如果您可能一次更改许多这些属性,那将会更有用。
答案 2 :(得分:1)
正如其他人指出的那样,使用std :: set或std :: multiset并不会削减它。
您可能没有注意到因为您使用指针,但假设对象是不可变的(尽管在这种情况下它意味着指针是const,但不是指向的值)。
因此,您不能(直接)使用将自动进行簿记的标准容器。
此时您有几种解决方案:
我认为两者都同样有效。由于操作非常简单,您可能不想使用Boost库(学习曲线,集成......)。
此外,您可以考虑使用“侵入式”容器。我的意思是你可以在这里使用'Observer'模式&gt;&gt;您的对象可以在每次更改其值时通知其容器,以便容器将其重新定位到其“新”正确位置(在内部使用std :: multiset)。
如果效率是一个问题,我不会考虑对矢量进行排序。每次更换单个对象时对整个容器进行排序是一种浪费,您的擦除/插入方法会更有效。