Guest User

Untitled

a guest
May 21st, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.78 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6. namespace FunctionalLists
  7. {
  8.     public sealed class Map<TKey, TValue> : IDictionary<TKey, TValue>
  9.     {
  10.         private struct Entry
  11.         {
  12.             public int Next;
  13.             public int HashCode;
  14.             public TKey Key;
  15.             public TValue Value;
  16.         }
  17.  
  18.         Entry[] entries;
  19.         int[] buckets;
  20.  
  21.         int entryCount;
  22.         int freeList;
  23.         int freeCount;
  24.  
  25.         int version;
  26.  
  27.         public IEqualityComparer<TKey> Comparer { get; private set; }
  28.  
  29.         public ICollection<TKey> Keys
  30.         {
  31.             get { throw new NotImplementedException(); }
  32.         }
  33.  
  34.         public ICollection<TValue> Values
  35.         {
  36.             get { throw new NotImplementedException(); }
  37.         }
  38.  
  39.         public TValue this[TKey key]
  40.         {
  41.             get
  42.             {
  43.                 int entryIndex = FindEntry(key);
  44.                 if (entryIndex < 0)
  45.                     throw new KeyNotFoundException();
  46.  
  47.                 return entries[entryIndex].Value;
  48.             }
  49.             set { Insert(key, value, false); }
  50.         }
  51.  
  52.         public int Count
  53.         {
  54.             get { return entryCount - freeCount; }
  55.         }
  56.  
  57.         public bool IsReadOnly
  58.         {
  59.             get { return false; }
  60.         }
  61.  
  62.         public Map()
  63.             : this(0, EqualityComparer<TKey>.Default)
  64.         {
  65.         }
  66.  
  67.         public Map(int capacity, IEqualityComparer<TKey> comparer)
  68.         {
  69.             if (capacity < 0)
  70.                 throw new ArgumentOutOfRangeException("capacity");
  71.             if (comparer == null)
  72.                 throw new ArgumentNullException("comparer");
  73.  
  74.             Comparer = comparer;
  75.  
  76.             int size = GetPrime(capacity);
  77.             entries = new Entry[size];
  78.             buckets = new int[size];
  79.  
  80.             for (int i = 0; i < buckets.Length; i++)
  81.             {
  82.                 buckets[i] = -1;
  83.             }
  84.  
  85.             entryCount = 0;
  86.             freeList = -1;
  87.             freeCount = 0;
  88.         }
  89.  
  90.         private void IncrementVersion()
  91.         {
  92.             version = unchecked(version + 1);
  93.         }
  94.  
  95.         private int GetPrime(int min)
  96.         {
  97.             if (min % 2 == 0)
  98.                 min = checked(min + 1);
  99.  
  100.             for (int i = Math.Max(min, 3); i < Int32.MaxValue; i += 2)
  101.             {
  102.                 bool isPrime = true;
  103.                 for (int j = 3; j < i; j++)
  104.                 {
  105.                     if (i % j == 0)
  106.                     {
  107.                         isPrime = false;
  108.                         break;
  109.                     }
  110.                 }
  111.  
  112.                 if (isPrime)
  113.                     return i;
  114.             }
  115.  
  116.             return min;
  117.         }
  118.  
  119.         private void Enlarge()
  120.         {
  121.             // at this point we know that entries
  122.             // array is full and freeList == -1
  123.  
  124.             int newSize = GetPrime(checked(entries.Length * 2));
  125.             Entry[] newEntries = new Entry[newSize];
  126.             int[] newBuckets = new int[newSize];
  127.  
  128.             for (int i = 0; i < newBuckets.Length; i++)
  129.             {
  130.                 newBuckets[i] = -1;
  131.             }
  132.  
  133.             Array.Copy(entries, 0, newEntries, 0, entryCount);
  134.  
  135.             for (int i = 0; i < entryCount; i++)
  136.             {
  137.                 int newBucket = newEntries[i].HashCode % newBuckets.Length;
  138.                 newEntries[i].Next = newBuckets[newBucket];
  139.                 newBuckets[newBucket] = i;
  140.             }
  141.  
  142.             buckets = newBuckets;
  143.             entries = newEntries;
  144.         }
  145.  
  146.         private void Insert(TKey key, TValue value, bool add)
  147.         {
  148.             int hash = Math.Abs(Comparer.GetHashCode(key));
  149.             int bucket = hash % buckets.Length;
  150.  
  151.             for (int i = buckets[bucket]; i >= 0; i = entries[i].Next)
  152.             {
  153.                 if (entries[i].HashCode == hash && Comparer.Equals(entries[i].Key, key))
  154.                 {
  155.                     if (add)
  156.                         throw new ArgumentException("Item with the same key already present in map.");
  157.  
  158.                     entries[i].Key = key;
  159.                     entries[i].Value = value;
  160.                     IncrementVersion();
  161.                     return;
  162.                 }
  163.             }
  164.  
  165.             int insertEntryIndex;
  166.             if (freeList >= 0)
  167.             {
  168.                 insertEntryIndex = freeList;
  169.                 freeList = entries[freeList].Next;
  170.                 freeCount--;
  171.             }
  172.             else
  173.             {
  174.                 // if entries array is full
  175.                 if (entryCount == entries.Length)
  176.                 {
  177.                     Enlarge();
  178.                     bucket = hash % buckets.Length;
  179.                 }
  180.  
  181.                 insertEntryIndex = entryCount;
  182.                 entryCount++;
  183.             }
  184.  
  185.             entries[insertEntryIndex].HashCode = hash;
  186.             entries[insertEntryIndex].Key = key;
  187.             entries[insertEntryIndex].Value = value;
  188.             entries[insertEntryIndex].Next = buckets[bucket];
  189.  
  190.             buckets[bucket] = insertEntryIndex;
  191.             IncrementVersion();
  192.         }
  193.  
  194.         private int FindEntry(TKey key)
  195.         {
  196.             int hash = Math.Abs(Comparer.GetHashCode(key));
  197.             int bucket = hash % buckets.Length;
  198.  
  199.             for (int i = buckets[bucket]; i >= 0; i = entries[i].Next)
  200.             {
  201.                 if (entries[i].HashCode == hash && Comparer.Equals(entries[i].Key, key))
  202.                     return i;
  203.             }
  204.  
  205.             return -1;
  206.         }
  207.  
  208.         public void Add(TKey key, TValue value)
  209.         {
  210.             Insert(key, value, true);
  211.         }
  212.  
  213.         public bool ContainsKey(TKey key)
  214.         {
  215.             return FindEntry(key) >= 0;
  216.         }
  217.  
  218.         public bool Remove(TKey key)
  219.         {
  220.             int hash = Math.Abs(Comparer.GetHashCode(key));
  221.             int bucket = hash % buckets.Length;
  222.  
  223.             int lastIndex = -1;
  224.             for (int i = buckets[bucket]; i >= 0; i = entries[i].Next)
  225.             {
  226.                 if (entries[i].HashCode == hash && Comparer.Equals(entries[i].Key, key))
  227.                 {
  228.                     if (lastIndex >= 0)
  229.                         entries[lastIndex].Next = entries[i].Next;
  230.                     else
  231.                         buckets[bucket] = entries[i].Next;
  232.  
  233.                     entries[i].HashCode = -1;
  234.                     entries[i].Key = default(TKey);
  235.                     entries[i].Value = default(TValue);
  236.                     entries[i].Next = freeList;
  237.                     freeList = i;
  238.                     freeCount++;
  239.  
  240.                     IncrementVersion();
  241.                     return true;
  242.                 }
  243.  
  244.                 lastIndex = i;
  245.             }
  246.  
  247.             return false;
  248.         }
  249.  
  250.         public bool TryGetValue(TKey key, out TValue value)
  251.         {
  252.             int entryIndex = FindEntry(key);
  253.             if (entryIndex >= 0)
  254.             {
  255.                 value = entries[entryIndex].Value;
  256.                 return true;
  257.             }
  258.             else
  259.             {
  260.                 value = default(TValue);
  261.                 return false;
  262.             }
  263.         }
  264.  
  265.         public void Clear()
  266.         {
  267.             if (entryCount == 0)
  268.                 return;
  269.  
  270.             for (int i = 0; i < buckets.Length; i++)
  271.             {
  272.                 buckets[i] = -1;
  273.             }
  274.  
  275.             Array.Clear(entries, 0, entryCount);
  276.             entryCount = 0;
  277.             freeList = -1;
  278.             freeCount = 0;
  279.             IncrementVersion();
  280.         }
  281.  
  282.         public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
  283.         {
  284.             int lastVersion = this.version;
  285.             for (int i = 0; i < entryCount; i++)
  286.             {
  287.                 // if element not removed
  288.                 if (entries[i].HashCode >= 0)
  289.                 {
  290.                     yield return new KeyValuePair<TKey, TValue>(
  291.                         entries[i].Key, entries[i].Value);
  292.  
  293.                     if (version != lastVersion)
  294.                         throw new InvalidOperationException("Map was changed during enumeration.");
  295.                 }
  296.             }
  297.         }
  298.  
  299.         void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
  300.         {
  301.             Insert(item.Key, item.Value, true);
  302.         }
  303.  
  304.         bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
  305.         {
  306.             int entryIndex = FindEntry(item.Key);
  307.             return entryIndex >= 0 &&
  308.                 EqualityComparer<TValue>.Default.Equals(
  309.                     item.Value, entries[entryIndex].Value);
  310.         }
  311.  
  312.         void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
  313.         {
  314.             if (array.Length - arrayIndex < Count)
  315.                 throw new ArgumentException("Array length is insufficient to hold items.");
  316.  
  317.             int index = arrayIndex;
  318.             foreach (var pair in this)
  319.             {
  320.                 array[index] = pair;
  321.                 index++;
  322.             }
  323.         }
  324.  
  325.         bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
  326.         {
  327.             int entryIndex = FindEntry(item.Key);
  328.  
  329.             if (entryIndex >= 0 &&
  330.                 EqualityComparer<TValue>.Default.Equals(
  331.                     item.Value, entries[entryIndex].Value))
  332.             {
  333.                 Remove(item.Key);
  334.                 return true;
  335.             }
  336.  
  337.             return false;
  338.         }
  339.  
  340.         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  341.         {
  342.             return this.GetEnumerator();
  343.         }
  344.     }
  345. }
Add Comment
Please, Sign In to add comment