我写的东西需要从一个数字列表开始,已按顺序但可能有间隙,找到第一个间隙,在该间隙中填入一个数字,然后返回它填写的数字。是[0,inf]范围内的整数。我有这个,它完美无缺:
list<int> TestList = {0, 1, 5, 6, 7};
int NewElement;
if(TestList.size() == 0)
{
NewElement = 0;
TestList.push_back(NewElement);
}
else
{
bool Selected = false;
int Previous = 0;
for(auto Current = TestList.begin(); Current != TestList.end(); Current++)
{
if(*Current > Previous + 1)
{
NewElement = Previous + 1;
TestList.insert(Current, NewElement);
Selected = true;
break;
}
Previous = *Current;
}
if(!Selected)
{
NewElement = Previous + 1;
TestList.insert(TestList.end(), NewElement);
}
}
但我担心效率,因为我使用等效的代码片段在我写的类包装器后面的OpenGL中分配统一的块绑定位置(但这与问题并不完全相关:))。有什么建议可以提高效率吗?我甚至不确定std :: list是否是它的最佳选择。
答案 0 :(得分:3)
一些建议:
尝试其他容器并进行比较。链表可能具有良好的理论属性,但连续存储的实际好处(例如在排序向量中)可能是戏剧性的。
由于您的范围已经订购,您可以执行二进制搜索以找到差距:从中间开始,如果值等于一半大小,则没有间隙,因此您可以限制搜索另一半。冲洗并重复。 (这假设范围内没有重复的数字,我认为这是一个合理的限制,因为你有一个“缺口”的概念。)
这更像是一个理论上的单独建议。纯链表上的二进制搜索无法高效实现,因此需要使用不同类型的数据结构来利用这种方法。
答案 1 :(得分:1)
一些建议:
基于std::vector
的 cursor gap structure (a.k.a。“缺口缓冲区”)可能是最快的(无论系统如何)。对于实现,请在开始时设置容量(从最大数字开始),以避免代价高昂的动态分配。
可以在光标间隙结构上使用二进制搜索,然后使用快速移动来移动插入点,但是如果你走这条路线则执行测量:通常是不好的方法非常多的项目,例如线性搜索,最适合少数项目。
保留调用之间的位置,因此您不必每次都从头开始,从O( n 中减少填写所有内容的总算法复杂度2 )到O( n )。
更新:根据OP的其他评论信息,这是分配和解除分配号码的情况,其中订单(显然)没关系,最快可能是使用 free list ,正如j_random_hacker的评论中所建议的那样。简而言之,首先将所有可用数字推入堆栈,例如,一个std::stack
,免费列表。要分配一个数字,只需将其从堆栈中弹出(选择堆栈顶部的数字),即可解除分配数字。