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
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();
}
}