繁体   English   中英

任何具有0(1)或O(Logn)复杂度的.net集合,用于查找和删除,添加和插入

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM