
[英]Why does ImmutableList have complexity O(logN) in its add method?
[英]Any .net collection which has complexity of 0(1) or O(Logn) for look up and remove, add and insert
我遇到一个非常奇怪的情况,我创建了一个ObservableList类,如下所示
class observableList<T>:IObservableList<T>, IList, IUserCollectionType
{
private List<T> _list;
private HashSet<T> _containedElements
// for each operation add,insert,remove I keep HashSet and List in synch.
}
}
我需要HashSet进行快速查找,但是HashSet没有排序的集合,我需要列表,因为我需要引发CollectionChanged事件,但是它需要项索引。 因此,要订购,我必须列出清单,而为了快速查找,我必须采用HashSet,
但是现在,我遇到了一个问题,即从列表中删除导致O(n)。 首先,我必须获取索引,然后使用removeAt()方法,因为必须引发集合更改事件,所以必须获取索引。
现在,我正在寻找一种解决方案,该解决方案的复杂度为O(1)或O(Logn),以进行查找以及移除以及排序。 我不能使用二分法,因为如果我将index作为键,并删除任何项目,则必须将项目的Key更新1。
**所以,为什么我们没有复杂度为O(1)或接近的集合
1.查找
2.对于删除,添加并插入。
3.收集应订购
在Java中,有人告诉我,可能有一个Linkedhashmap类,但是我不确定。 因此,.NET是否有此集合的替代品。
还是我们有任何具有此类集合的开源库?
通过从.Net的LinkedList<T>
和Dictionary<K,V>
类中构建与Java的LinkedHashSet
类似的东西,可以获得所需的性能。 这样可以为您提供O(1)查找,插入和删除以及保留插入顺序。
我在下面草绘此解决方案; 请注意,这排除了诸如检查重复元素或实际实现IObservableList部分以及您可能需要的一些其他方法之类的问题。 另请注意,这基本上是伪代码,我没有对其进行编译或测试。
class LinkedHashSet<T>
{
private LinkedList<T> _list;
private Dictionary<T, LinkedListNode<T>> _containedElements
public void Add(T value)
{
LinkedListNode<T> newNode = _list.AddLast(value);
_containedElements[value] = newNode;
}
public void Remove(T value)
{
LinkedListNode<T> node = _containedElements[value];
_containedElements.Remove(value);
_list.Remove(node);
}
public bool Contains(T value)
{
return _containedElements.ContainsKey(value);
}
}
编辑:解决整个问题
正如我在评论中已经说过的那样,我注意到以上内容并不是该问题的完整解决方案,因为该问题还涉及其他操作:在给定项目的列表中查找索引(至少在移除)。
我没有完全解决这个问题的解决方案,但是我确实有一个可行的想法,因此,这里的答案是更完整的:
您可以将以上示例中的LinkedList
替换为平衡的二叉树结构(例如,红黑树)。 该树中的每个节点都引用一个值(就像链表中的每个节点一样),并且每个节点还将其后代的计数存储在树中。
您可以通过从根开始降序并在左侧最多保留i
节点来在O(log(n))时间中按其索引i
查找任何元素。 由于每个节点都可以帮助您告知其后代计数,因此您只需查看遇到的每个节点的左子节点,即可确定是否需要继续向左或向右(或者当前节点是否包含目标)。
除了需要更新所有受影响的节点及其祖先的后代计数之外,插入或删除元素的操作与以前一样在Red-Black树中完成。 我没有完全解决这部分问题,但是我很确定这在O(log(n))时间内仍然可行,就像“正常”的红黑树一样。
最后,您可以在O(log(n))时间中找到任何元素的索引,方法是从它的节点开始,然后沿着树走,对左边的所有节点进行计数(再次利用每个节点的降序计数)。 在上面的示例中,字典本身会引用该节点本身,因此您实际上可以高效地找到它。
总之 ,将上述示例中的LinkedList
替换为此处描述的树数据结构,将为您提供O(log(n))插入,删除,按值查找索引和按索引查找值,O(1)遍历(摊销), O(1)包含检查,所有这些都假定Dictionary操作与O(1)一起使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.