我的c ++程序需要维护2个对象列表。
list<A*> inuse;
list<A*> free;
所以对象A甚至可以在“使用中”列表或“免费”列表中,但不能同时在两者中 http://www.cplusplus.com/reference/stl/list/
我想使用'list'作为我的列表的数据结构。 我的问题是
inuse[2]
; 谢谢。
答案 0 :(得分:7)
使用std::vector。
它具有随机元素访问权限([]
或at()
)。
//does NOT check for out of range
myvector[i];
//does check for out of range
myvactor.at(i);
您可以使用erase()从矢量中删除元素,它会自动处理漏洞(#3变为#2,依此类推)
//erase the 6th element
myvector.erase (myvector.begin()+5);
// erase the first 3 elements:
myvector.erase (myvector.begin(),myvector.begin()+3);
但是如果您需要逐个删除多个对象,并且列表中不能有2个相同的对象,则可以尝试使用std::map。使用object的一些唯一属性作为键,并将itselt对象作为值(或对象本身为键,true
作为值)。它还具有类似的随机访问运算符[]
和erase()
函数。
答案 1 :(得分:6)
遗憾的是,恒定时间删除和固定时间随机访问是互斥的。
使用线性时间std::list
的{{1}}进行随机访问,或使用std::advance
(我的推荐)或std::deque
并接受线性时间删除。
如果你总是删除系列中的第二项,std::vector
有可能保持不变的删除时间。 deque
与deque
类似,但分为与内容列表相关联的小块。
或者,如果您的数据已排序,请使用vector
进行固定时间删除和日志(N)时间访问。
从任何容器中删除项目由std::set
完成。列表,矢量,双端队列,地图,等等。
答案 2 :(得分:6)
如果你需要快速访问和快速删除,请考虑std :: set,它应该同时具有logn查找和logn insert / delete,同时仍然被排序
答案 3 :(得分:0)
std::list是在名为doubly linked list的数据结构之后建模的。
您不能使用随机访问,因为对象位于堆上,指向其位置的指针存储在上一个和下一个元素中。在std :: vector中,内存是连续的,你可以通过对象的偏移*大小来访问第n个元素。
通过获取该对象的迭代器并使用该迭代器(或范围)调用std :: list :: erase来删除元素。 erase返回一个迭代器,该迭代器指向您刚删除的元素的下一个指针所指向的元素。
是的,该地点将自动填补。
所有人都说,如果有疑问,请使用std :: vector。
答案 4 :(得分:0)
std :: list是一个双向链表。这意味着您有一系列包含元素的节点,如此
a&lt; - &gt; b - &lt; - &gt; c - &lt; - &gt; d。
当你删除'b'时,会发生的事情是指针被调整,以便节点a指向节点c,b被删除,即
A&LT; - &GT;℃下; - &GT; d
没有[]运算符的原因是,如果要查找第5个元素,则需要按照指向第5个元素的链接。数据结构不支持快速访问特定位置。在数组或向量中,所有元素都是彼此相邻的,因此这是微不足道的。您只需将5 * sizeof(数据)添加到指向顶部的指针。
deque也允许快速访问,但快速插入和删除只能从正面或背面进行。
我怀疑你真正想要的是std :: set或std :: map,这样你就可以找到该元素并快速移动到另一个元素。
答案 5 :(得分:0)
list<>
是一个相当差的名字;它实际上是一个链表。你想要vector<>
(.Net的List<>
和Java的ArrayList
。)
答案 6 :(得分:0)
我在这里猜测很多......但是......
我认为您需要能够使用这两个列表执行不同的操作。听起来你正在编写某种池化分配器。
我希望,“免费列表”只需要让你从前面推出弹出;它是一个fifo堆栈,可用于存储当前未使用但可在需要分配且“空闲列表”当前不为空时使用的对象。
“活动列表”是所有当前分配的对象的列表。分配器可能需要能够报告这些,或者对它们做任何事情,或者其他什么。 “活动列表”要求您可以在取消分配对象时从任何位置删除对象。我猜它会被推到免费列表中重复使用。
现在,可用于每个“列表”的数据结构可能不同。这一切都取决于具体要求。如果我在所需的使用语义上是正确的,我会说你应该能够使用std::list<A *>
作为你的“免费列表”。如果您不关心能够按分配顺序走“活动列表”,那么您可以使用std::set<A *>
作为“活动列表”。为了避免需要在集合中执行查找以从“活动列表”中删除对象,您可以将迭代器存储到对象集合中对象的位置(除非对象本身从对象中移除,否则此迭代器不会失效)设置 - 或者说这个answer并且我没有检查它但是我确信有人会纠正我,如果我错了)。如果您需要能够按照分配顺序遍历“活动列表”,那么您可以使用std::map<size_t, A *>
并将递增分配索引存储为映射键;再次'对象持有快速擦除的迭代器'技巧应该有效。
答案 7 :(得分:0)
我将“inuse”和“free”列表实现为双向链表,然后创建数组“inuse_pointers”和“free_pointers”来保存指向列表元素的指针。这样,您可以使用指针数组索引链接列表(并避免必须遍历列表),并将保持双向链接列表的快速插入/删除操作。这不是一种典型的STL方法(这是从我目前正在处理的一些C语言缓存管理代码中获取的)但我知道它有效且效率很高。