快速收集比较

时间:2012-10-01 19:27:25

标签: c# data-structures

我有以下数据类型:

ISet<IEnumerable<Foo>> 

所以,我需要能够创建一系列序列。例如。这没关系:

ABC,AC,A

但这不是(因为“AB”在这里重复“):

AB,A,ABC,BCA,AB

但是,为了做到这一点 - 为了使“set”不包含重复项,我需要将IEnumerable包装成某种其他数据类型:

ISet<Seq>
//where
Seq : IEnumerable<Foo>, IEquatable<Seq>

因此,我将能够比较两个序列,并为Set数据结构提供一种消除重复的方法。

我的问题是:是否存在允许比较序列的快速数据结构?我想在某种程度上创建Seq或添加两个时,会计算某种累积值。

换句话说,是否可以以这样的方式实现Seq:

var seq1 = new Seq( IList<Foo> );
var seq2 = new Seq( IList<Foo> )
seq1.equals(seq2) // O(1)

感谢。

2 个答案:

答案 0 :(得分:2)

我在下面提供了一个实现序列。有几点需要注意:

  1. 仅当IEnumerable<T>每次枚举时返回相同的项目,并且这些项目在此对象的范围内不会发生变异时,此方法才有效。
  2. 缓存哈希码。第一次请求时,它会根据底层序列的完整迭代计算它(如果你知道更好的话,可以随意改进哈希码算法)。因为它只需要计算一次,如果经常计算,这可以有效地被认为是O(1)。添加到集合中可能会慢一点(第一次计算哈希值),但搜索或删除会非常快。
  3. equals方法首先比较哈希码。如果哈希码不同,则对象不可能相等(如果哈希码在序列中的所有对象上正确实现,并且没有任何变异)。只要你的碰撞率很低,并且通常比较实际上不相等的项目,这意味着等于检查通常不会超过该哈希码检查。如果他们这样做,则需要迭代序列(没有办法解决)。因为等于可能平均为O(1),即使最坏的情况仍为O(n)。

    public class Foo:IEnumerable {     私有IEnumerable序列;

    private int? myHashCode = null;
    
    public Foo(IEnumerable<T> sequence)
    {
        this.sequence = sequence;
    }
    
    public IEnumerator<T> GetEnumerator()
    {
        return sequence.GetEnumerator();
    }
    
    IEnumerator IEnumerable.GetEnumerator()
    {
        return sequence.GetEnumerator();
    }
    
    public override bool Equals(object obj)
    {
        Foo<T> other = obj as Foo<T>;
        if(other == null)
            return false;
    
        //if the hash codes are different we don't need to bother doing a deep equals check
        //the hash code is cached, so it's fast.
        if (GetHashCode() != obj.GetHashCode())
            return false;
    
        return Enumerable.SequenceEqual(sequence, other.sequence);
    }
    
    public override int GetHashCode()
    {
        //note that the hash code is cached, so the underlying sequence 
        //needs to not change.
        return myHashCode ?? populateHashCode();
    }
    
    private int populateHashCode()
    {
        int somePrimeNumber = 37;
        myHashCode = 1;
        foreach (T item in sequence)
        {
            myHashCode = (myHashCode * somePrimeNumber) + item.GetHashCode();
        }
    
        return myHashCode.Value;
    }
    

    }

答案 1 :(得分:1)

O(1)实质上意味着不允许比较元素的值。如果您可以将序列表示为不可变对象的列表(添加缓存以便所有实例都没有重复),您可以实现它,因为您只需要比较第一个元素 - 类似于字符串实习的工作方式。

Insert必须搜索“current”+“with this next”元素的所有元素实例。某种字典可能是合理的方法......

编辑:我认为它只是试图提出suffix tree