using System; using System.Collections.Generic; class LinkedHashMap{ Dictionary >> D = new Dictionary >>(); LinkedList > LL = new LinkedList >(); public U this[T c] { get { return D[c].Value.Item1; } set { if(D.ContainsKey(c)) { LL.Remove(D[c]); } D[c] = new LinkedListNode >(Tuple.Create(value, c)); LL.AddLast(D[c]); } } public bool ContainsKey(T k) { return D.ContainsKey(k); } public U PopFirst() { var node = LL.First; LL.Remove(node); D.Remove(node.Value.Item2); return node.Value.Item1; } public int Count { get { return D.Count; } } } class LinkedHashMapTest { public static void Test() { var lhm = new LinkedHashMap (); lhm['a'] = 1; lhm['b'] = 2; lhm['c'] = 3; Console.WriteLine(lhm['a']); Console.WriteLine(lhm['b']); Console.WriteLine(lhm['c']); Console.WriteLine(lhm.PopFirst()); Console.WriteLine(lhm.PopFirst()); Console.WriteLine(lhm.PopFirst()); } }
CSharp does not have a SortedMultiSet
using System; using System.Collections; using System.Collections.Generic; // Duck-taped SortedMultiSet by using a SortedSet and custom comparer function. public class SortedMultiSet: IEnumerable { SortedSet data; public SortedMultiSet(Comparer fn) { bool refType = default(T) == null; if (!refType) throw new Exception ("Will not work for value types."); var fnd = Comparer .Create( (a, b) => { int r = fn.Compare(a,b); if(r == 0) { // If same object (no matter values), is the same. // Be careful because struct or objects that compare by value will not work. if(a.Equals(b)) return 0; // If not (same values according to compare function, but a // distinct object), we give a consistent but arbitrary order. if(a.GetHashCode() < b.GetHashCode()) return -1; return 1; } return r; }); this.data = new SortedSet (fnd); } public int Count { get { return this.data.Count; } } public void Add(T v) { this.data.Add(v); } public void Remove(T v) { this.data.Remove(v); } public T Min() { return this.data.Min; } public T Max() { return this.data.Max; } public IEnumerator GetEnumerator() { return this.data.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } public class Run { class Node { public int i; public int v; public Node(int i, int v) { this.i = i; this.v = v; } public override string ToString() { return string.Format("i: {0}, v: {1}", this.i, this.v); } } public static void UnitTest (IEnumerable set, List vec, Func equal) { int i = 0; foreach(var v in set) { Console.WriteLine(string.Format("{0}, {1}", v, vec[i])); if(!equal(v, vec[i])) throw new Exception(); ++i; } } public static void UnitTestInts() { var smset = new SortedMultiSet ( Comparer .Create( (a, b) => a.CompareTo(b) ) ); var vec = new List (); var random = new Random(Environment.TickCount); const int n = 100000; for(int i = 0; i < n; ++i) { int v = random.Next(0, n/10); vec.Add(v); smset.Add(v); } vec.Sort(); UnitTest(smset, vec, (a,b) => a == b); } public static void UnitTestCustomClass() { var cmpFn = Comparer .Create( (a, b) => a.v.CompareTo(b.v) ); var smset = new SortedMultiSet ( cmpFn ); var vec = new List (); var random = new Random(Environment.TickCount); const int n = 100000; for(int i = 0; i < n; ++i) { int v = random.Next(0, n/10); var node = new Node(i, v); vec.Add(node); smset.Add(node); } vec.Sort( cmpFn ); UnitTest(smset, vec, (a,b) => a.v == b.v); } public static void UnitTestRemoveCustom() { var cmpFn = Comparer .Create( (a, b) => a.v.CompareTo(b.v) ); var smset = new SortedMultiSet ( cmpFn ); // Should be able to remove self. var node = new Node(0, 0); if(smset.Count != 0) throw new Exception(); smset.Add(node); if(smset.Count != 1) throw new Exception(); smset.Remove(node); if(smset.Count != 0) throw new Exception(); smset.Add(node); if(smset.Count != 1) throw new Exception(); // Different node with same value, should be independent. var node2 = new Node(0, 0); smset.Add(node2); if(smset.Count != 2) throw new Exception(); smset.Add(node2); if(smset.Count != 2) throw new Exception(); smset.Add(node); if(smset.Count != 2) throw new Exception(); smset.Remove(node); if(smset.Count != 1) throw new Exception(); smset.Remove(node); if(smset.Count != 1) throw new Exception(); smset.Remove(node2); if(smset.Count != 0) throw new Exception(); } public static void UnitTestRemoveValueType() { var cmpFn = Comparer .Create( (a, b) => a.CompareTo(b) ); var smset = new SortedMultiSet ( cmpFn ); // Should be able to remove same. if(smset.Count != 0) throw new Exception(); smset.Add(1); if(smset.Count != 1) throw new Exception(); smset.Remove(1); if(smset.Count != 0) throw new Exception(); smset.Add(1); if(smset.Count != 1) throw new Exception(); // Different node with same value, should be independent. smset.Add(2); if(smset.Count != 2) throw new Exception(); smset.Add(2); if(smset.Count != 3) throw new Exception(); smset.Add(1); if(smset.Count != 4) throw new Exception(); smset.Remove(1); if(smset.Count != 3) throw new Exception(); smset.Remove(1); if(smset.Count != 2) throw new Exception(); smset.Remove(2); if(smset.Count != 1) throw new Exception(); smset.Remove(1); if(smset.Count != 0) throw new Exception(); smset.Remove(1); if(smset.Count != 0) throw new Exception(); } public static void Main() { // UnitTestInts(); UnitTestCustomClass(); UnitTestRemoveCustom(); // UnitTestRemoveValueType(); } }
If you do not care at all about performance (you just want to have something that will respect the SortedMultiset behavior), here is a silly version that justs uses a vector underneath and re-sorts for every insert.
using System; using System.Collections; using System.Collections.Generic; // C# does not have a SortedMultiSet, use this class if you need the interface for verifications, // but do not care about performance. // // This does NOT use a red-black tree as storage (it justs re-sorts a basic linear DS), // so the performance will be horrible. public class FakeSortedMultiSet: IEnumerable { List data; Comparer compareFn; public FakeSortedMultiSet() : this(null) { this.data = new List (); } public FakeSortedMultiSet(Comparer fn) { this.data = new List (); this.compareFn = fn; } public int Count { get { return this.data.Count; } } public void Add(T v) { this.data.Add(v); // Obviously, this is really silly performance-wise. this.data.Sort(this.compareFn); } public void Remove(T v) { this.data.Remove(v); } public T Min() { return this.data[0]; } public T Max() { return this.data[this.data.Count-1]; } public IEnumerator GetEnumerator() { return this.data.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } public class Run { class Node { public int i; public int v; public Node(int i, int v) { this.i = i; this.v = v; } public override string ToString() { return string.Format("i: {0}, v: {1}", this.i, this.v); } } public static void Main() { var sortedVector = new FakeSortedMultiSet (); var vector = new List (); vector.Add( 10 ); vector.Add( 3 ); vector.Add( 5 ); vector.Add( 5 ); vector.Add( 5 ); vector.Add( 100 ); vector.Add( 1 ); foreach(var v in vector) { sortedVector.Add(v); } vector.Sort(); int i = 0; foreach(var v in sortedVector) { if( v != vector[i] ) throw new Exception(); ++i; } var nodes = new List (); nodes.Add( new Node(7, 10) ); nodes.Add( new Node(10, 1) ); nodes.Add( new Node(1, -234) ); nodes.Add( new Node(3, 100) ); var sortedNodes = new FakeSortedMultiSet ( Comparer .Create( (a, b) => a.v.CompareTo(b.v) ) ); foreach(var v in nodes) { sortedNodes.Add(v); } nodes.Sort( (a,b) => a.v.CompareTo(b.v) ); i = 0; foreach(var v in sortedNodes) { Console.WriteLine(v); if( v != nodes[i] ) throw new Exception(); ++i; } } }