代码常用结构

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)

posted @ 2020-10-20 12:31  Elijah_j  阅读(215)  评论(0编辑  收藏  举报