字典

65 阅读2分钟

字典的基本使用

添加

    Dictionary<string, int> dic_test = new Dictionary<string, int>();
    dic_test.Add("Ada",33);
    dic_test["Alice"] = 30;
    
    //添加已经在字典中已经存在的键,会有异常
    //eg: dic_test.Add("Ada", 24);
    //不存在Ada键,则添加成功,返回true,否则不修改,并返回false
    dic_test.TryAdd("Ada", 38);
    

访问

dic_test["Ada"];

若键不存在,会抛出异常

不抛出异常处理方法

//bobAge访问范围与同级
	if(dic_test.TryGetValue("Ada", out int bobAge)) {
		Console.WriteLine($"Ada的年龄是:{bobAge}");
	}
	else {
		Console.WriteLine("未找到Ada键的值");
	}
	Console.WriteLine($"Ada的年龄是:{bobAge}");
        
        

删除

Console.WriteLine(dic_test.Romove("Ada"));
Console.WriteLine(dic_test.Romove("Ada",out int CarlAge));//删除成功返回true

ContainsKey和ContainsValue方法

if(dic_test.ContainsKey("Ada"))
    Console.WriteLine("包含Ada键");
if(dic_test.ContainsValue(18))
    Console.WriteLine("包含值 18");

字典的使用场景

  1. 数据索引
  2. 统计频次
  3. 缓存数据

Dictionary的实现原理

关键算法:Hash算法和解决Hash碰撞冲突的算法

Hsh算法是一种数字摘要算法,将不定长度的二进制数据集给映射到一个较短的二进制长度数据集。实现Hash算法的函数称为Hash函数。

private struct Entry{
    public int hashCode;
    public int next;
    public TKey key;
    public TValue value;

}
private int[] buckets;
private Entry[] entries;

dic.Add("a",111);

  1. hashCode(a) = 10;
  2. 10%7=3
  3. buckets[3] = 0;
  4. 把值存在Entry类型数组里,位置为0
  5. 长度不够会扩容,长度为素数,因为对素数取余得到的余数冲突的概率最小,可以均匀分布在数组中

因为得到的余数可能会有相同的值,所以会冲突

解决方法

在Entry结构体中,添加了next,如果在同数组下标,添加了多个数据,那会在next记录原来这个位置的值,记录原理的下标,在通过键找到对应的下标后,判断此下标的对应的结构体里的Key是不是与自己的键值相等,相等则取结构体Entry内的value值,否则,通过该结构体的next值查询原来该位置的值,重复判断到找到相同的Key

image.png