Are there any implementations of multiset for .Net?
我正在寻找多集的.NET实现。有人能推荐一个好的吗?
(多集或包是一组具有重复值的集合,您可以在其上执行设置操作:交叉点、差异等。例如,购物车可以被视为多集,因为您可以多次出现同一产品。)
任何称自己为多集C实现的东西都不应该基于内部词典。字典是散列表、无序集合。C++的集合、多集、映射和多任务是有序的。在内部,每个都表示为自平衡二进制搜索树的某种风格。
在C中,我们应该使用SortedDictionary作为实现的基础,因为根据微软自己的文档,SortedDictionary"是具有O(log n)检索的二进制搜索树"。基本多集可以实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | public class SortedMultiSet<T> : IEnumerable<T> { private SortedDictionary<T, int> _dict; public SortedMultiSet() { _dict = new SortedDictionary<T, int>(); } public SortedMultiSet(IEnumerable<T> 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<T> 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<T> GetEnumerator() { foreach(var kvp in _dict) for(int i = 0; i < kvp.Value; i++) yield return kvp.Key; } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } |
我不知道有一个,但是你可以用一个
另一种可能是简单地使用一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | public class Multiset<T>: ICollection<T> { private readonly Dictionary<T, int> data; public Multiset() { data = new Dictionary<T, int>(); } private Multiset(Dictionary<T, int> data) { this.data = data; } public void Add(T item) { int count = 0; data.TryGetValue(item, out count); count++; data[item] = count; } public void Clear() { data.Clear(); } public Multiset<T> Except(Multiset<T> another) { Multiset<T> copy = new Multiset<T>(new Dictionary<T, int>(data)); foreach (KeyValuePair<T, int> kvp in another.data) { int count; if (copy.data.TryGetValue(kvp.Key, out count)) { if (count > kvp.Value) { copy.data[kvp.Key] = count - kvp.Value; } else { copy.data.Remove(kvp.Key); } } } return copy; } public Multiset<T> Intersection(Multiset<T> another) { Dictionary<T, int> newData = new Dictionary<T, int>(); foreach (T t in data.Keys.Intersect(another.data.Keys)) { newData[t] = Math.Min(data[t], another.data[t]); } return new Multiset<T>(newData); } public bool Contains(T item) { return data.ContainsKey(item); } public void CopyTo(T[] array, int arrayIndex) { foreach (KeyValuePair<T, int> kvp in data) { for (int i = 0; i < kvp.Value; i++) { array[arrayIndex] = kvp.Key; arrayIndex++; } } } public IEnumerable<T> Mode() { if (!data.Any()) { return Enumerable.Empty<T>(); } int modalFrequency = data.Values.Max(); return data.Where(kvp => kvp.Value == modalFrequency).Select(kvp => kvp.Key); } public int Count { get { return data.Values.Sum(); } } public bool IsReadOnly { get { return false; } } public bool Remove(T item) { int count; if (!data.TryGetValue(item, out count)) { return false; } count--; if (count == 0) { data.Remove(item); } else { data[item] = count; } return true; } public IEnumerator<T> GetEnumerator() { return new MultisetEnumerator<T>(this); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return new MultisetEnumerator<T>(this); } private class MultisetEnumerator<T> : IEnumerator<T> { public MultisetEnumerator(Multiset<T> multiset) { this.multiset = multiset; baseEnumerator = multiset.data.GetEnumerator(); index = 0; } private readonly Multiset<T> multiset; private readonly IEnumerator<KeyValuePair<T, int>> baseEnumerator; private int index; public T Current { get { return baseEnumerator.Current.Key; } } public void Dispose() { baseEnumerator.Dispose(); } object System.Collections.IEnumerator.Current { get { return baseEnumerator.Current.Key; } } public bool MoveNext() { KeyValuePair<T, int> kvp = baseEnumerator.Current; if (index < (kvp.Value - 1)) { index++; return true; } else { bool result = baseEnumerator.MoveNext(); index = 0; return result; } } public void Reset() { baseEnumerator.Reset(); } } } |