代码常用结构
https://www.cnblogs.com/xiaomowang/p/12405639.html
上述网址写的很详细
1.DIctionary
先从entry开始说起:
这是一个结构体(包含 哈希值,下一个entry的地址,键值,数值啊)
1.1.初始化
private void Initialize(int capacity) { int size = HashHelpers.GetPrime(capacity); buckets = new int[size]; for (int i = 0; i < buckets.Length; i++) buckets[i] = -1; entries = new Entry[size]; freeList = -1; }
HashHelper.cs
public static int GetPrime(int min) {
if (min < 0) throw new ArgumentException(Environment.GetResourceString("Arg_HTCapacityOverflow")); Contract.EndContractBlock(); for (int i = 0; i < primes.Length; i++) { int prime = primes[i]; if (prime >= min) return prime; } //outside of our predefined table. //compute the hard way. for (int i = (min | 1); i < Int32.MaxValue;i+=2) { if (IsPrime(i) && ((i - 1) % Hashtable.HashPrime != 0)) return i; } return min; }
public static bool IsPrime(int candidate)
{
if ((candidate & 1) != 0)//不是0
{
int limit = (int)Math.Sqrt(candidate);
for (int divisor = 3; divisor <= limit; divisor += 2)
{
if ((candidate % divisor) == 0)
return false;
}
return true;
}
return (candidate == 2);
}
1.2.插入(修改ASDCD)
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; int targetBucket = hashCode % buckets.Length; //根据这个(targetBucket)在buckets中找到对应数组并遍历这个根据entry中的next看看是不是已经有值了(替换) //如果没有对应位置获取entries中第一个空的位置并添加上,如果已经满了,增加容量并重新初始化
1.3.删除
根据hashcode生成的bucket找到entries,。在对应entries中找到对应值然后置空
1.4.查找
1.4.1 下标查找也是根据ashcode生成的bucket找到entries然后遍历entries
1.5.遍历
遍历数组entries
2.vector
二维数组,三维数组(并对数组中的项封装了一些方法)
3.IList
public interface IList<T> : ICollection<T> { // The Item property provides methods to read and edit entries in the List. T this[int index] { get; set; } // Returns the index of a particular item, if it is in the list. // Returns -1 if the item isn't in the list. int IndexOf(T item); // Inserts value into the list at position index. // index must be non-negative and less than or equal to the // number of elements in the list. If index equals the number // of items in the list, then value is appended to the end. void Insert(int index, T item); // Removes the item at position index. void RemoveAt(int index); }
4.List
public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T> { private const int _defaultCapacity = 4; private T[] _items;//明显看出这里就是数组 [ContractPublicPropertyName("Count")] private int _size; private int _version; [NonSerialized] private Object _syncRoot; static readonly T[] _emptyArray = new T[0];
5.Hashtable
// The hash table data. // This cannot be serialised private struct bucket { public Object key; public Object val; public int hash_coll; // Store hash code; sign bit means there was a collision. } private bucket[] buckets;
初始化
double rawsize = capacity / this.loadFactor;//loadfactor默认是1.0 if (rawsize > Int32.MaxValue) throw new ArgumentException(Environment.GetResourceString("Arg_HTCapacityOverflow")); // Avoid awfully small sizes int hashsize = (rawsize > InitialSize) ? HashHelpers.GetPrime((int)rawsize) : InitialSize; buckets = new bucket[hashsize];
插入
private uint InitHash(Object key, int hashsize, out uint seed, out uint incr) { // Hashcode must be positive. Also, we must not use the sign bit, since // that is used for the collision bit. uint hashcode = (uint) GetHash(key) & 0x7FFFFFFF; seed = (uint) hashcode; // Restriction: incr MUST be between 1 and hashsize - 1, inclusive for // the modular arithmetic to work correctly. This guarantees you'll // visit every bucket in the table exactly once within hashsize // iterations. Violate this and it'll cause obscure bugs forever. // If you change this calculation for h2(key), update putEntry too! incr = (uint)(1 + ((seed * HashPrime) % ((uint)hashsize - 1))); return hashcode; }
do-while里面查找bucketNumber = (int) (((long)bucketNumber + incr)% (uint)buckets.Length); 有没有位置,没有位置更新数组位置
do { // 现在如果有的话(hash_coll<0,把当前计算好的位置赋值给emptySlotNumber) if (emptySlotNumber == -1 && (buckets[bucketNumber].key == buckets) && (buckets[bucketNumber].hash_coll< 0))//(((buckets[bucketNumber].hash_coll & unchecked(0x80000000))!=0))) emptySlotNumber = bucketNumber; //这里是如果值为空,直接加进去 if ((buckets[bucketNumber].key == null) || (buckets[bucketNumber].key == buckets && ((buckets[bucketNumber].hash_coll & unchecked(0x80000000))==0))) { if (emptySlotNumber != -1) // Reuse slot bucketNumber = emptySlotNumber; buckets[bucketNumber].val = nvalue; buckets[bucketNumber].key = key; buckets[bucketNumber].hash_coll |= (int) hashcode; return; } // //这里找着找着好像key完全一样,那就替换对应数值 if (((buckets[bucketNumber].hash_coll & 0x7FFFFFFF) == hashcode) && KeyEquals(buckets[bucketNumber].key, key)) { buckets[bucketNumber].val = nvalue; return; } // The current bucket is full, and we have therefore collided. We need to set the collision bit // UNLESS // we have remembered an available slot previously. if (emptySlotNumber == -1) {// We don't need to set the collision bit here since we already have an empty slot if(buckets[bucketNumber].hash_coll >= 0 ) { buckets[bucketNumber].hash_coll |= unchecked((int)0x80000000); occupancy++; } } //这里如果都走完事会刷新长度并重新计算hash值 bucketNumber = (int) (((long) bucketNumber + incr)% (uint) buckets.Length); } while (++ntry<buckets.Length);
6.SortedDictionary
//TreeSet遍历返回的
private KeyCollection keys;
//TreeSet遍历返回的
private ValueCollection values;
//双向链表插入
private TreeSet<KeyValuePair<TKey, TValue>> _set;
7.HashSet
internal struct Slot { internal int hashCode; // Lower 31 bits of hash code, -1 if unused internal T value; internal int next; // Index of next entry, -1 if last }
private int[] m_buckets; private Slot[] m_slots;
int capacity = m_siInfo.GetInt32(CapacityName);
总结 hashset hashtable dictionary
hashtable 只有一个数组,如果重复的话根据一个int取或然后找到第一个空位子放着(key跟value都装箱拆箱)
dictionary 跟hashset 两个数组,都是第一个存另外一个数组的位置,然后数组里找next(字典是key,value,set只有value)