C++ 在位置i处插入元素并返回基于第一个元素i的信息
假设我有一个整数列表:C++ 在位置i处插入元素并返回基于第一个元素i的信息,c++,algorithm,performance,data-structures,C++,Algorithm,Performance,Data Structures,假设我有一个整数列表: 2, 1, 3, 1, 4, 2, 5, 3, 2 我希望能够在位置I插入一个新的整数。假设i是4,我想插入数字7。结果将是: 2, 1, 3, 7, 1, 4, 2, 5, 3, 2 插入后,我希望收到一些基于I和更低位置的数字的信息。例如,第一个i数字的总和。在这种情况下,它将是2+1+3+7=13 我希望能够一次又一次地重复这个过程 我用C++编写了一个程序,使用了 STD::List。下面是它在i位置插入n到List中,然后返回i第一个数字的总和的操作: 将上
2, 1, 3, 1, 4, 2, 5, 3, 2
我希望能够在位置I
插入一个新的整数。假设i
是4,我想插入数字7。结果将是:
2, 1, 3, 7, 1, 4, 2, 5, 3, 2
插入后,我希望收到一些基于I
和更低位置的数字的信息。例如,第一个i
数字的总和。在这种情况下,它将是2+1+3+7=13
我希望能够一次又一次地重复这个过程
<>我用C++编写了一个程序,使用了<代码> STD::List。下面是它在i
位置插入n
到List
中,然后返回i
第一个数字的总和的操作:
k
与i
进行比较。如果它较低,则对每个j:k
计算sum[j]
,如下:sum[j]=sum[j-1]+List[j]
-O(n)i
-O(n)i
位置插入n
,存储k=i
-O(1)sum[i]=sum[i-1]+n
-O(1)是否可以使用不同的数据结构来更有效地实现这一点?也许在O(logn)里?如果是,那么怎么做?如果您想要一个开箱即用的解决方案,而不需要滚动新的数据结构或使用第三方库,
std::vector
将是您的最佳选择。算法复杂性为:
2, 1, 3, 7, 1, 4, 2, 5, 3, 2
k
与i
进行比较。如果较低,则计算总和:O(n)
O(1)
或O(n)
如果涉及某种搜索。如果涉及到搜索,它仍将大大快于std::list
i
位置插入n
:O(n)
sum[i]=sum[i-1]+n
:O(1)
std::vector
对这一点非常有用,我们最终受益于它对上述4种情况的快速、连续、顺序访问
std::list
与std::allocator
一起使用时(尤其是在并非所有节点都一次分配的上下文中),往往会调用大量缓存未命中,因为它缺少空间位置(另一方面,部分原因是列表指针的开销减少了可以放入缓存线的元素数量,在这种特殊情况下,这主要是因为我们要求每个小整数有两个列表指针)
请注意,当您在标准库之外冒险时,可能会有更多的最佳解决方案,这些库针对您的特定问题进行了调整,如另一个很好的答案中所述。深入研究较低级别细节的另一个角度是寻找您自己的自定义分配器,它可以真正帮助任何类型的链接结构。这个答案集中于在《香草C++》中,<>代码>矢量< /代码>通常是你的最佳选择(除非有其他强烈的理由)当处理顺序容器时,给定其连续的、缓存友好的表示。正如@andyg在评论中提到的,这是一项适合Fenwick树或二元索引树的工作。二元索引树可以在
O(logn)
中进行插入和更新,并在O(logn)中进行查询(从开始到索引的总和)
。有一篇关于二叉索引树的非常好的文章
同样,这项工作也可以用段树完成,但由于二元索引树的实现非常简单,我建议使用二元索引树。乍一看,这听起来像是一项针对a的工作,
n
元素的总和需要O(n),但使用std::vector
时速度会更快。查找位置是O(1)对于std::vector
。您可以用它来交换插入O(n)。在短列表中使用std::vector
会快得多。在大数据集上,这取决于需要移位的程度,但向量在其操作中正好位于后面。我只想指出,位置4实际上是1所在的位置,因为数组中的位置从0开始计数