Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用C++ STD::集作为类的构建块?_C++_Algorithm_Stl_Generic Programming_Stdset - Fatal编程技术网

如何使用C++ STD::集作为类的构建块?

如何使用C++ STD::集作为类的构建块?,c++,algorithm,stl,generic-programming,stdset,C++,Algorithm,Stl,Generic Programming,Stdset,我需要满足以下条件的数据结构: 存储任意数量的元素,其中每个元素由10个数字指标描述 允许按任何指标对元素进行快速日志n搜索 允许快速插入新元素 允许快速删除元素 让我们假设元素的构造成本很高 我想出了以下计划 将所有元素存储在称为数据的向量中。 使用10个std::集合,每10个度量值对应一个。每个std:set都是轻量级的,它只包含整数,整数是向量数据的索引。比较运算符“查找”数据中的适当元素,然后选择适当的度量 元素永远不会从向量中修改或删除。将新元素推回数据,然后将其索引DATA.siz

我需要满足以下条件的数据结构:

存储任意数量的元素,其中每个元素由10个数字指标描述 允许按任何指标对元素进行快速日志n搜索 允许快速插入新元素 允许快速删除元素 让我们假设元素的构造成本很高

我想出了以下计划

将所有元素存储在称为数据的向量中。 使用10个std::集合,每10个度量值对应一个。每个std:set都是轻量级的,它只包含整数,整数是向量数据的索引。比较运算符“查找”数据中的适当元素,然后选择适当的度量 元素永远不会从向量中修改或删除。将新元素推回数据,然后将其索引DATA.size-1插入到集合中。为了删除一个元素,我在元素中设置了一个标志,表示它已被删除,而没有从数据向量中实际删除它,然后从所有十个std::集合中删除元素索引

只要数据是全局变量,这种方法就可以正常工作。它还通过使模板化结构Cmp依赖于全局变量而在某种程度上滥用了类型系统

但是,我无法将数据向量和std::set的集合封装在类中,然后用这些std::set“索引”数据。首先,在外部类中定义的比较运算符Cmp无法访问外部类的字段,因此无法评估数据。我也无法将向量传递给Cmp构造函数,因为Cmp是由std::set构造的,并且std::set需要一个比较运算符,该运算符的构造函数没有参数

我有一种感觉,我正在反对C++类型的系统,试图实现某种类型系统故意阻止我做的事情。我试图使std::set依赖于一个只在运行时构造的变量。虽然我理解为什么类型系统可能不喜欢我所做的,但我认为这是一个合法的用例


有没有一种方法可以在不重新实现std::set/red-black-tree的情况下实现上述数据结构/类I?我希望可能有一个我还没有想到的把戏。是的,我知道boost有一些东西,但我想坚持使用标准库。

当我读到类似于通过值栏查找foo的内容时,我的最初反应是使用地图或类似的东西。不过,这有一些含义:

std::map中的键或std::set中的值是唯一的,因此没有两个元素可以共享同一个键,因此没有两个数据对象能够具有相同的度量。如果多个数据对象可以具有相同的度量,这在您的问题中并不清楚,但是使用std::multimap或std::multiset也可以。 如果键是常量并且存储在元素本身中,则使用集合是一种常见的方法。然后,比较器仅从对象中检索相应字段并对其进行比较。然后,查找需要创建一个临时对象并使用find。一些实现还有一个扩展,允许使用不同的类型进行搜索,这将使这更容易,但也使移植需要实际工作。 但是,用作键的字段保持不变是很重要的,因为如果修改它们,则会隐式更改集合的顺序。这就是集合元素实际上是常量的原因,即即使是普通迭代器也有一个常量作为值类型。但是,如果存储指针,您可以轻松绕过它,因为常量指针与指向常量的指针不同。别用那东西打自己的脚! 如果度量不是对象本身的属性,或者您不介意冗余存储它们,那么使用std::map将是一个自然选择。根据度量,在多个键下存储同一对象可以在单独的容器map c[10];。但是,您可以在单个映射中使用,例如,将一对作为密钥映射c;。 使用一个向量来存储实际的元素,并且只将它们作为指针或索引引用到映射中,这肯定是可行的。不过,我会使用指针,因为这是允许使用集合或映射的上述方法工作的原因。否则,比较器将不得不存储对容器的引用,此时它只使用全局数据容器。不过,要让它与向量一起工作是很棘手的,因为正如您正确指出的,它在增长时会重新分配其元素。我会考虑一种不同的容器类型,比如STD::List或STD::DeQue.前者也允许擦除元素,但它具有更高的每元素开销。后者的每元素开销相对较低,仅略高于std::vector。然后,您甚至可以存储迭代器而不是指针,这有助于调试,前提是您使用检查过的STL。不过,你还是得做些什么 手动簿记哪些对象在某处仍被引用,哪些不被引用。 您也可以动态地分配元素,而不是使用单独的容器,尽管这本身有一些开销。如果每个元素的开销不是问题,那么可以使用引用计数的智能指针。如果应用程序是一个一次性进程,那么您还可以使用原始指针,让操作系统在退出时回收内存。
注意,我假设存储数据对象的多个副本不是一个选项。如果是这样的话,你也可以有一张地图m[10];,其中每个地图存储其自己的数据对象副本。所有簿记问题都将得到解决,但代价是10倍的开销。

数据将保留的元素量大约是多少?度量是否为每个数据对象生成唯一的值?在我看来,您似乎想要实现某种索引数据库表。是的,我知道boost有一些功能,但我想坚持使用标准库。似乎正是你想要的。。你必须使用一个库或者自己编写一个库。显然,你可以在集中存储指针而不是整数,然后你可以轻松地访问比较器中对象的任何属性。我知道你提到了关于大O复杂性的约束,但是你考虑过仅仅是一个向量吗?如果数据类型不太大,元素的数量也不太多,那么会有很多非常有趣的资料显示,连续内存布局在实际时间方面具有优势,您可以利用可用的缓存。您的里程数可能会有所不同,请在提交前测量。1是。至于2,避免使用原始指针;使用智能指针。3也是。对于4,这是一个X-Y解。另外,擦除元素在其他容器中也有效,但没有那么快。谢谢您的评论,@Qix,确实3中的措词丢失了。你提出的其他观点本身有点不清楚,尤其是第一点,看起来你好像没有花时间去理解我写的所有内容。然后我会重复一些。你的一些观点似乎被套牢了。好吧,不是太套牢了,以至于你无法清楚地反驳它们是错误的。说真的,你能说得更具体些吗?你的观点没有任何意义。1所有元素都保证是唯一的,检查Cmp操作符,我发布它是因为一个原因2正确但与问题无关,你可以争辩我不应该释放内存两次3???你会使用指向向量中元素的指针或迭代器吗?这样就更难调试了?所以一旦向量重新分配,整个事情就会爆炸?最后,你说我应该把整个事情适当地封装起来。我认为整个问题是关于如何封装它,以及它是否可行
template< int C >
struct Cmp
{
    bool operator() (int const a, int const b)
    {
        return ( DATA[a].coords[C] != DATA[b].coords[C] ) 
           ? ( DATA[a].coords[C] < DATA[b].coords[C] )
           : ( a < b );
    }
};