C++ 哪个数据结构是按插入排序的,并且具有fast“;包括「;支票?
我正在寻找一种数据结构,它保留元素插入的顺序,并提供一个快速的“contains”谓词。我还需要迭代器和随机访问。插入或删除期间的性能不相关。我也愿意接受内存消耗方面的开销 背景:我需要存储一个对象列表。这些对象是名为C++ 哪个数据结构是按插入排序的,并且具有fast“;包括「;支票?,c++,performance,data-structures,C++,Performance,Data Structures,我正在寻找一种数据结构,它保留元素插入的顺序,并提供一个快速的“contains”谓词。我还需要迭代器和随机访问。插入或删除期间的性能不相关。我也愿意接受内存消耗方面的开销 背景:我需要存储一个对象列表。这些对象是名为Neuron的类的实例,存储在层中。层对象具有以下公共接口: class Layer { public: Neuron *neuronAt(const size_t &index) const; NeuronIterator begin(); Neu
Neuron
的类的实例,存储在层
中。层
对象具有以下公共接口:
class Layer {
public:
Neuron *neuronAt(const size_t &index) const;
NeuronIterator begin();
NeuronIterator end();
bool contains(const Neuron *const &neuron) const;
void addNeuron(Neuron *const &neuron);
};
当软件运行时,contains()
方法经常被调用,我断言使用callgrind。我试图绕过对contains()
的一些调用,但仍然是一个热点。现在我希望能对这个方法进行优化
我考虑使用std::set
,使用template参数来提供我自己的comparator结构。但是神经元
类本身并没有给出它在层
中的位置。另外,我想让*someneuronitoriterator=anotherNeuron
在不破坏顺序的情况下工作
另一个想法是使用普通的旧C数组。由于我不关心添加一个新的Neuron
对象的性能,我想我可以确保Neuron
对象总是线性存储在内存中。但这会使我传递给addNeuron()
的指针无效;至少我必须将其更改为指向我创建的新副本,以保持线性对齐。对吧?
另一个想法是在层
对象中使用两种数据结构:用于顺序的向量/列表和用于查找的映射/哈希。但这与我希望的迭代器相矛盾,迭代器允许运算符*
不使用常量引用,不是吗
我希望有人能给我一个能满足我需求的数据结构或概念的想法,或者至少给我一个替代方案的想法。谢谢 堆似乎对你有用。它就像一棵树,但最新的元素总是插入到顶部,然后根据其值向下移动,因此有一种方法可以快速检查它是否存在
否则,您可以存储一个哈希表(用于检查表中是否包含神经元的快速方法),其中包含神经元的键、值:神经元本身以及插入神经元的时间步长(以检查其按时间顺序的插入时间).如果此
包含
检查确实是您需要最快执行的地方,并且假设您可以稍微侵入源代码,检查神经元是否属于某个层的最快方法是在将其插入层时对其进行标记(例如:位标记)
在这一点上,你保证了O(1)检查,看一个神经元是否属于一个层,并且在微观层面上也很快
如果可以有许多层对象,这可能会变得有点棘手,因为神经元可能属于的每个潜在层都需要一个单独的位,除非一个neuron
一次只能属于一个层。但是,如果层的数量在大小上相对固定,这是可以合理管理的
如果后一种情况和神经元一次只能属于一个层,那么您所需要的只是一个指向层*
的反向指针。要查看神经元是否属于某个层,只需查看该反向指针是否指向该层对象
如果一个Neuron
可以同时属于多个层,但一次不能属于太多层,那么您可以像存储一个小数组一样存储,如下所示:
struct Neuron
{
...
Layer* layers[4]; // use whatever small size that usually fits the common case
Layer* ptr;
int num_layers;
};
初始化ptr
以指向层
,前提是神经元所属的层不超过4层。如果有更多,在免费商店分配。在析构函数中,如果ptr!=图层
。如果常见情况类似于1层,您还可以优化掉num_layers
,在这种情况下,以null结尾的解决方案可能会更好。要查看神经元是否属于某一层,只需通过ptr
进行线性搜索。对于神经元的数量来说,这实际上是恒定的时间复杂度,前提是它们不同时属于大量的层
您也可以在此处使用向量
,但您可能会减少这些常见情况下的缓存命中,因为它总是将其内容放在单独的块中,即使神经元仅属于1或2层
这可能与您所寻找的通用、非侵入式数据结构有所不同,但如果您的性能需求确实偏向于这些类型的集合操作,那么侵入式解决方案通常是最快的。它并没有那么漂亮,并将您的元素耦合到容器,但是,嘿,如果您需要最大的性能
另一个想法是使用普通的旧C数组。由于我不关心添加新神经元对象的性能,我想我可以确保神经元对象在内存中总是线性存储。但这会使我传递给addNeuron()的指针无效;[……]
是的,但它不会使索引无效。虽然不像指针那样方便使用,但如果您正在处理网格顶点或发射器粒子等海量数据,通常在此处使用索引以避免无效,并可能在64位系统上为每个条目节省额外的32位
更新
考虑到神经元一次只存在于一层中,我会采用反向指针法。查看一个神经元是否属于某一层就变成了一个简单的问题,即检查后指针是否指向同一层
由于涉及到一个API,我建议,仅仅因为听起来你在推送大量数据,并且已经对其进行了分析,所以你应该关注一个围绕聚合(例如,层)而不是单个的接口