Are there any implementations of multiset for .Net?

后端 未结 3 1206
梦谈多话
梦谈多话 2020-12-18 18:11

I\'m looking for a .Net implementation of a multiset. Can anyone recommend a good one?

(A multiset, or bag, is a set that can have duplicate values, and on which you

3条回答
  •  有刺的猬
    2020-12-18 18:25

    Anything calling itself a C# implementation of a multiset should not be based on a Dictionary internally. Dictionaries are hash tables, unordered collections. C++'s sets, multisets, maps, and multimaps are ordered. Internally each is represented as some flavor of a self-balancing binary search tree.

    In C# we should then use a SortedDictionary as the basis of our implementation as according to Microsoft's own documentation a SortedDictionary "is a binary search tree with O(log n) retrieval". A basic multiset can be implemented as follows:

    public class SortedMultiSet : IEnumerable
    {
        private SortedDictionary _dict; 
    
        public SortedMultiSet()
        {
            _dict = new SortedDictionary();
        }
    
        public SortedMultiSet(IEnumerable items) : this()
        {
            Add(items);
        }
    
        public bool Contains(T item)
        {
            return _dict.ContainsKey(item);
        }
    
        public void Add(T item)
        {
            if (_dict.ContainsKey(item))
                _dict[item]++;
            else
                _dict[item] = 1;
        }
    
        public void Add(IEnumerable items)
        {
            foreach (var item in items)
                Add(item);
        }
    
        public void Remove(T item)
        {
            if (!_dict.ContainsKey(item))
                throw new ArgumentException();
            if (--_dict[item] == 0)
                _dict.Remove(item);
        }
    
        // Return the last value in the multiset
        public T Peek()
        {
            if (!_dict.Any())
                throw new NullReferenceException();
            return _dict.Last().Key;
        }
    
        // Return the last value in the multiset and remove it.
        public T Pop()
        {
            T item = Peek();
            Remove(item);
            return item;
        }
    
        public IEnumerator GetEnumerator()
        {
            foreach(var kvp in _dict)
                for(int i = 0; i < kvp.Value; i++)
                    yield return kvp.Key;
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
    

提交回复
热议问题