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);
}
}
c# 字典 底层逻辑
最新推荐文章于 2024-04-21 17:49:09 发布