public StringDictionaryWithKey(StringDictionaryWithKey <T> copyDictionary) { _capacity = copyDictionary._capacity; _capacityLess1 = copyDictionary._capacityLess1; _entries = new StringDictionaryEntryWithKey <T> [_capacity]; //copyDictionary._entries.CopyTo(_entries, 0); _spaceMap = new BitArray(copyDictionary._spaceMap); Count = copyDictionary.Count; }
public StringDictionaryWithKey() // : this(0) { _capacity = 8; // (capacity > _minCapacity ? GetNextCapacity(capacity) : _minCapacity); _capacityLess1 = _capacity - 1; // Minimum capacity of StringDictionary = 1024 entries _entries = new StringDictionaryEntryWithKey <T> [_capacity]; // Initialize the space map _spaceMap = new BitArray(_capacity); }
/// <summary> /// This methods adds a given Key value pair to the StringDictionary. Keys need to be unique. Values need not be unique. /// Complexity Average Case: O(log((n + 1/)n)), Worst Case: O(n) /// </summary> /// <param name="key"></param> /// <param name="keyValue"></param> public void Add(string key, T keyValue) { //GetHashCodes(key, out hashA, out hashB); uint hashA = 0, hashB = 0; for (int i = 0; i < key.Length; i++) { hashA = ((hashA << 5) + hashA ^ (uint)key[i]); hashB = ((hashB << 6) + (hashB << 16) - hashB + (uint)key[i]); } uint hash; bool inserted = false; lock (_syncRoot) { for (int i = 0; i < _numHashes; i++) { hash = hashA + _primes[i] * hashB; int index = (int)(hash & _capacityLess1); if (!_spaceMap[index]) { _entries[index] = new StringDictionaryEntryWithKey <T>(hashA, hashB, keyValue, key); inserted = true; _spaceMap[index] = true; break; } } if (!inserted) { while (!inserted) { Resize(); for (int i = 0; i < _numHashes; i++) { hash = hashA + _primes[i] * hashB; if (!_spaceMap[(int)(hash & _capacityLess1)]) { _entries[hash & _capacityLess1] = new StringDictionaryEntryWithKey <T>(hashA, hashB, keyValue, key); inserted = true; _spaceMap[(int)(hash & _capacityLess1)] = true; break; } } } } Count++; } }
/// <summary> /// The number of hashes to generate for insertions / lookups in the StringDictionary. /// The default value is 31. Possible values range from 5 to 277 inclusive. A lower value leads to greater performance at the cost of a low load factor. /// A higher value leads to lesser performance but higher load factor. /// </summary> //public int NumHashes //{ // get { return _numHashes; } // set { _numHashes = ((value < 16) && (value > 278) ? value : 31); } //} // Indexer //public T this[string key] //{ // get // { // //int index; // //if ((index = ContainsKeyInternal(key)) >= 0) // // return _entries[index].Value; // //else // // return default(T); // return this.GetContainsKey(key); // } // //set // //{ // // int index; // // if ((index = ContainsKeyInternal(key)) >= 0) // // _entries[index].Value = value; // // else // // throw new KeyNotFoundException("Key not found. Key: " + key); // //} //} #endregion #region Utility Functions /// <summary> ///// The internal method used by ContainsKey(string) method. ///// </summary> ///// <param name="key"></param> ///// <returns></returns> //private int ContainsKeyInternal(string key) //{ // uint hashA, hashB; // uint hash; // GetHashCodes(key, out hashA, out hashB); // for (int i = 0; i < _numHashes; i++) // { // hash = hashA + _primes[i] * hashB; // if (!_spaceMap[(int)(hash & _capacityLess1)]) // break; // else if (_entries[hash & _capacityLess1].HashA == hashA && _entries[hash & _capacityLess1].HashB == hashB) // return (int)(hash & _capacityLess1); // } // return -1; //} /// <summary> /// The internal method called to resize the _entries array. /// Complexity O(n) /// </summary> private void Resize() { start: _capacity = _capacity << 1; _capacityLess1 = _capacity - 1; StringDictionaryEntryWithKey <T>[] newEntries = new StringDictionaryEntryWithKey <T> [_capacity]; BitArray newSpaceMap = new BitArray(_capacity); uint hash; for (int i = 0; i < _entries.Length; i++) { if (_spaceMap[i]) { bool rehashed = false; for (int j = 0; j < _numHashes; j++) { hash = _entries[i].HashA + _primes[j] * _entries[i].HashB; if (!newSpaceMap[(int)(hash & _capacityLess1)]) { newEntries[hash & _capacityLess1] = _entries[i]; newSpaceMap[(int)(hash & _capacityLess1)] = true; rehashed = true; break; } } if (!rehashed) { //Debug.Assert(false, "rehash goto accured."); goto start; } } } _entries = newEntries; _spaceMap = newSpaceMap; }