c# 字典 底层逻辑

using System;
using System.Collections;
using System.Collections.Generic;
public class MyDict<K, V>: IEnumerable
{
    
    
    struct Entry
    {
    
    
        public int hash;
        public int next;
        public K key;
        public V value;
    }

    public struct Enumerator :  IEnumerator
    {
    
    
        MyDict<K, V> dict;
        int index;
        int version;
        KeyValuePair<K, V> current;
        public KeyValuePair<K, V> Current => current;
        object IEnumerator.Current
        {
    
    
            get
            {
    
    
                if (index == 0 || index == dict.count + 1)
                    Console.WriteLine("遍历报错");
                return new KeyValuePair<K, V>(current.Key, current.Value);
            }
        }
        public bool MoveNext()
        {
    
    
            if (version != dict.version)
                Console.WriteLine("版本号不一致");// 遍历的时候不能修改
            while (index < dict.count)
            {
    
    
                if (dict.entrys[index].hash >= 0)
                {
    
    
                    current = new KeyValuePair<K, V>(dict.entrys[index].key, dict.entrys[index].value);
                    index++;
                    return true;
                }
                index++;
            }
            index = dict.count + 1;
            return false;
        }

        public void Reset()
        {
    
    
            index = 0;
            current = default(KeyValuePair<K, V>);
        }
        public Enumerator(MyDict<K,V> dict)
        {
    
    
            this.dict = dict;
            index = 0;
            version = dict.version;
            current = default(KeyValuePair<K, V>);
        }
    }

    private int version;

    private int count;
    private int freeCount;
    private int freeList;// 空闲的索引

    private Entry[] entrys;
    private int[] buckets;

    public int Count {
    
     get => count - freeCount; }       

    public MyDict()
    {
    
    
    }

    public void Clear()
    {
    
    
        if (count > 0)
        {
    
    
            version++;
            count = 0;
            freeCount = 0;
            freeList = -1;
            Array.Clear(entrys, 0, count);
            for (int i = 0; i < buckets.Length; i++)
                buckets[i] = -1;
        }
    }

    public V this[K key]
    {
    
    
        get
        {
    
    
            int index = FindEntry(key);
            if (index > 0)
                return entrys[index].value;
            else
            {
    
    
                Console.WriteLine("找不到 key:" + key);
                return default(V);
            }
        }
        set
        {
    
    
            Insert(key, value, false);
        }
    }

    private void Initialize(int capacity)
    {
    
    
        int prime = 3;
        buckets = new int[prime];
        for (int i = 0; i < buckets.Length; i++)
            buckets[i] = -1;
        entrys = new Entry[prime];
        freeList = -1;
    }

    public void Add(K key, V value)
    {
    
    
        Insert(key, value, true);
    }

    private void Insert(K key,V value,bool add)
    {
    
    
        if (key == null) return;
        if (buckets == null)
            Initialize(0);
        /// hash 值
        int hash = key.GetHashCode() & 0x7FFFFFFF;
        /// 放在 buckets 的索引
        int bi = hash % buckets.Length;
        for(int num = buckets[bi]; num >= 0; num = entrys[num].next)
        {
    
    
            if (entrys[num].hash == hash && entrys[num].key.Equals(key)) 
            {
    
    
                if (add)
                {
    
    
                    Console.WriteLine("key 值重复:" + key);
                    return;
                }
                entrys[num].value = value;
                version++;
                return;
            }
        }
        int c;
        /// 有空位置 先用空位置
        if (freeCount > 0) 
        {
    
    
            c = freeList;
            freeList = entrys[freeList].next;
            freeCount--;
        }
        else
        {
    
    
            /// 满了 扩充
            if (count == entrys.Length)
            {
    
    
                ReSize();
                /// 索引重新计算
                bi = hash % buckets.Length;
            }
            c = count;
            count++;
        }
        entrys[c].key = key;
        entrys[c].value = value;
        entrys[c].hash = hash;
        entrys[c].next = buckets[bi];
        buckets[bi] = c;
        version++;
    }

    private void ReSize()
    {
    
    
        Resize(entrys.Length * 2);
    }
    private void Resize(int size)
    {
    
    
        Entry[] a1 = new Entry[size];
        int[] a2 = new int[size];
        for (int i = 0; i < size; i++)
            a2[i] = -1;
        Array.Copy(entrys, 0, a1, 0, count);
        /// 在 buckets 中索引发生改变
        int index;
        for(int i = 0; i < count; i++)
        {
    
    
            if (a1[i].hash >= 0) 
            {
    
    
                index = a1[i].hash % size;
                a1[i].next = a2[index];
                a2[index] = i;
            }
        }
        entrys = a1;
        buckets = a2;
    }

    public bool Remove(K key)
    {
    
    
        if (key == null || buckets == null) return false;
        int hash = key.GetHashCode() & 0x7FFFFFFF;
        int bi = hash % buckets.Length;
        int before = -1;// 前一个索引
        for (int num = buckets[bi]; num >= 0; num = entrys[num].next)
        {
    
    
            if (entrys[num].hash == hash && entrys[num].key.Equals(key))
            {
    
    
                /// 删除时 如果是链表头 就把下一个设为链表头
                if (before != -1)
                    entrys[before].next = entrys[num].next;
                else
                    buckets[bi] = entrys[num].next;
                entrys[num].hash = -1;
                entrys[num].next = freeList;
                entrys[num].key = default(K);
                entrys[num].value = default(V);
                freeList = num;
                freeCount++;
                version++;
                return true;
            }
            before = num;
        }
        return false;
    }

    public bool ContainsKey(K key)
    {
    
    
        return FindEntry(key) >= 0;
    }
    public bool TryGetValue(K key, out V value)
    {
    
    
        int index = FindEntry(key);
        if (index > 0)
        {
    
    
            value = entrys[index].value;
            return true;
        }
        value = default(V);
        return false;
    }

    private int FindEntry(K key)
    {
    
    
        if (key == null || buckets == null)
            return -1;
        int hash = key.GetHashCode() & 0x7FFFFFFF;
        int bi = hash % buckets.Length;
        for(int num = buckets[bi]; num >= 0; num = entrys[num].next)
        {
    
    
            if (entrys[num].hash == hash && entrys[num].key.Equals(key))
            {
    
    
                return num;
            }
        }
        return -1;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
    
    
        throw new NotImplementedException();
    }
    public Enumerator GetEnumerator()
    {
    
    
        return new Enumerator(this);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_42235716/article/details/128289920