有趣的是,这可能是一个堆栈溢出问题

时间:2009-05-11 14:52:39

标签: c# list big-o micro-optimization

以下程序(以下说明)适用于非常小的列表,但当列表包含大量项目(1/2万)时,应用程序进入“无响应”状态,完成大约需要2.5分钟(非常糟糕的时间)。 我可能会添加应用程序需要处理1亿个项目的列表 至少(最终)。

这是有问题的程序的代码:

    public void removeItems(List<long> L, SortedList<long, List<long>> _subLists)
    {
        foreach (KeyValuePair<long, List<long>> kvp in _subLists)
        {
            foreach (long duplicate in kvp.Value)
            {
                int j = L.IndexOf(duplicate);
                L.RemoveRange(j,(int)kvp.Key); 

            }
        }
    }

L是长值列表。 _subLists是一个排序列表,其中每个值都是一个列表 来自L的值,开始一些差异的算术级数序列(不相关)。 与该值关联的键是值包含的序列的长度。

示例:

L = {1,2,3,5,6,7,18,20,21} _subLists = {2,&lt; 20&gt;}             {3,&LT; 1,5-&GT;}

该程序只是从L中删除算术级数序列。

3 个答案:

答案 0 :(得分:10)

此过程在大O表示法中的运行时间将是n ^ 2,这相当慢,如果其中一个列表有1亿个条目,则可以预期运行时间较慢。这里没有堆栈溢出问题,迭代这么多数据的速度很慢。我真的没有在这里看到一个问题,你是否想要加快速度?如果是这样,嵌套的for循环肯定是问题。

答案 1 :(得分:8)

你的问题是你要从L中移除很多物品,这是一项非常昂贵的操作。每次删除项目时,都会复制内存以将已删除项目上方的所有项目向下移动。删除的项目越多,随机播放的项目越多,所需的时间就越长。内存是性能的瓶颈,RAM运行速度比CPU慢,如果你正在分页到磁盘而不是真的很慢。

你怎么能改善这一点。

最简单的选择是在删除项目时使用L具有更好性能的容器 - 例如LinkedList。 LinkedLists在删除元素时不需要在内存中移动项目,但是它们需要更多内存来存储数据(每个值两个指针)。如果这是一个太多的开销,那么可能是LinkedList <List <long>>而不是每个List <long>保存最大数量的值。

或者,更改删除算法,以便迭代列表L并创建一个包含_subLists中未找到的值的新列表。您可以更改_subLists存储数据的方式,以便更快地查找范围内的项目。

答案 2 :(得分:0)

如果可能的话:

A)将L转换为已排序的链接列表。 O:n * log(n)

B)将子列表转换为排序列表对,其中第一项是L中序列中的#(在发布的代码片段中重复),第二项是序列的长度。 O:n * log(n)

C)使用子列表执行单次传递,以确定要在L中的给定位置移除多少元素。利用这两个列表在两个列表中排序为不回溯的事实。 O:n

如果可以使用,应该能够获得O:n * log(n)复杂度。 当然,我对这个问题的所有细节都不是100%肯定的。例如 - L可以重复吗?如果是这样,子列表的顺序是否重要?根据对这些算法的回答,您可能会被迫抛弃或修改此类算法。此外,这显然会占用更多内存。