我正在优化已排序的LinkedList的实现。
要插入一个元素,我遍历列表并比较每个元素,直到我有正确的索引,然后断开循环并插入。
我想知道是否有任何其他方法可以在遍历列表的同时插入元素以减少插入从O(n +(n capped at size()/ 2))到O (n)的
由于其add()方法,ListIterator 几乎我之后的东西,但不幸的是,如果列表中的元素等于insert,则必须在它们之后放置insert在列表中。要实现这个ListIterator需要一个它没有的peek()。
编辑:我有我的答案,但无论如何都会添加这个,因为很多人都没有正确理解: 我正在搜索插入点和插入,其组合高于O(n)
答案 0 :(得分:2)
您可以考虑skip list,它是使用不同粒度的多个链接列表实现的。例如。级别0的链接列表包含所有项目,级别1仅链接到平均每个第2项,级别2仅平均每4个项目等等。搜索从顶层开始逐渐下降到较低级别,直到它找到完全匹配。该逻辑类似于二进制搜索。因此,搜索和插入是O(log n )操作。
Java类库中的一个具体示例是ConcurrentSkipListSet
(虽然它可能在这里不能直接使用)。
答案 1 :(得分:1)
我赞成PéterTörök的建议,但我仍然想为迭代器方法添加一些内容:
请注意ListIterator
提供previous()
方法向后迭代列表。因此,首先迭代,直到找到第一个更大的元素,然后转到上一个元素并调用add(...)
。如果你到达终点,即所有元素都较小,那么只需调用add(...)
而不返回。
答案 2 :(得分:0)
我有我的答案,但无论如何都会添加这个,因为很多人都没有正确理解:我正在搜索插入点和插入,其组合高于
O(n)
。
您需要维护(可能)非唯一元素的集合,这些元素可以按照排序函数给出的顺序进行迭代。这可以通过多种方式实现。 (在下文中,我使用“总插入成本”来表示将数字(N
)元素插入到最初为空的数据结构中的成本。)
单个或双向链接列表提供O(N^2)
总插入成本(无论您是否结合找到位置和插入的步骤!)和O(N)
迭代成本。< / p>
TreeSet提供O(NlogN)
总插入费用和O(N)
次迭代费用。但是没有重复的限制。
基于树的多集(例如TreeMultiset
)与TreeSet具有相同的复杂性,但允许重复。
跳过列表数据结构也与前两个相同。
显然,复杂度测量表明,当N变大时,使用链表的数据结构会执行最差。对于这组特定的需求,假设只有一个线程访问集合,那么基于树的多重集合可能是最好的。如果许多线程大量使用该集合(并且它是一个集合),那么ConcurrentSkipListSet
可能更好。
你似乎也对“大O”措施如何结合产生了误解。如果我的算法的一步是O(N)
,第二步也是O(N)
,那么合并的两个步骤仍然是O(N)
....而不是“超过{{ 1}}”。你可以从“大O”的定义中得出这个。 (我不会厌烦你的细节,但数学很简单。)