【C#】Dictionary底层实现

Dictionary的键值对映射是通过哈希算法的函数建立的。这里不对哈希算法做过多的解释,算法本身就是将不定长度的键(可以是整数、字符串或对象)转化成一个固定值。

字典的关键成员

csharp 复制代码
private struct Entry
{
    public int hashCode;
    public int next;
    public K key;//字典中键的类型
    public V value;//字典中值的类型
}

private int[] buckets;//哈希桶数组
private Entry[] entries;//数据实体数组

buckets作用:存储entries 数据实体数组的索引

存储原理(添加键值对)

1.通过哈希(Hash)算法获取键的哈希值,赋值到数据实体 中hashCode

2.将hashCode对buckets数组长度取余(%)获得buckets数组中的buckets下标

3.通过buckets下标获得buckets数组中的元素(即为entries下标)

a.元素有效(!= -1)代表buckets 的索引位置 存储了 entries数组中索引,将当前元素赋值给Entry数据实体的next,并将Entry数据实体的索引赋值给buckets数组中的元素

b.元素无效(== -1)代表buckets 的索引位置 没有 entries数组中索引,将Entry数据实体的索引赋值给buckets数组中的元素

存储例子

插入数据A

csharp 复制代码
Dictionary.Add("a", 123);
  1. 假设* 通过哈希(Hash)算法获取键("a")的值为10
  2. 将10对buckets数组长度取余(%)获得buckets数组中的索引2
  3. 通过 下标2 获得buckets数组中的buckets2
  4. buckets2 == -1 代表buckets 的索引位置 没有 entries数组中索引,将Entry数据实体的索引赋值给buckets数组中的元素,即buckets2 = 0

插入数据B

csharp 复制代码
Dictionary.Add("qwe", 456);
  1. 假设* 通过哈希(Hash)算法获取键("qwe")的值也为10
  2. 将10对buckets数组长度取余(%)获得buckets数组中的索引2
  3. 通过 下标2 获得buckets数组中的buckets2
  4. buckets2 != -1 代表buckets 的索引位置 存储了 entries数组中索引,将当前元素赋值给Entry数据实体的next,即数据B的next = buckets2 = 0,并将Entry数据实体的索引赋值给buckets数组中的元素,即buckets2 = 1

读取原理(通过键获取值)

  1. 通过哈希(Hash)算法获取键的哈希值,赋值到数据实体 中hashCode
  2. 将hashCode对buckets数组长度取余(%)获得buckets数组中的buckets下标
  3. 通过buckets下标获得buckets数组中的元素(即为entries下标)
  4. 根据下标获取entries中的数据,判断Entry数据的key是否与想获取的相同
    a. 相同,返回Entry数据的value
    b. 不相同,根据Entry数据的next获取entries中的数据,直到key与想获取的相同,才返回value

读取例子

获取数据A

csharp 复制代码
Dictionary["a"]
  1. 假设* 通过哈希(Hash)算法获取键("a")的哈希值,赋值到数据实体为10
  2. 将10对buckets数组长度取余(%)获得buckets数组中的索引2
  3. 通过 索引2 获得buckets数组中的 buckets2 = 1
  4. 根据 1 获取entries中的数据,判断 entries1.key == "a"?
  5. (entries1.key) = "qwe" != "a",根据Entry数据的next获取entries中的数据 entriesnext = entries0,直到key与想获取的相同 entries0.key == "a",才返回entries0.value = 123

获取数据B

csharp 复制代码
Dictionary["qwe"]
  1. 假设* 通过哈希(Hash)算法获取键("a")的哈希值,赋值到数据实体为10
  2. 将10对buckets数组长度取余(%)获得buckets数组中的索引2
  3. 通过 索引2 获得buckets数组中的 buckets2 = 1
  4. 根据 1 获取entries中的数据,判断 entries1.key == "qwe"?
  5. 相同,返回entries1.value = 456

因为作者精力有限,文章中难免出现一些错漏,敬请广大专家和网友批评、指正。

相关推荐
Evand J1 小时前
【MATLAB例程介绍】(17)永磁同步电机(PMSM)基于自适应无迹卡尔曼滤波(AUKF)的电流噪声在线估计。测量噪声协方差自适应与转速估计对比仿真
开发语言·matlab·卡尔曼滤波·无迹卡尔曼滤波·pmsm·电机滤波
Coder_Shenshen2 小时前
罗克韦尔ACD工程归档离线变量树解析
算法·c#
BaiPeter2 小时前
ZPL文件预览
开发语言·c++
噢,我明白了8 小时前
JAVA中的一些基础应用知识点
java·开发语言
寂寞的船8 小时前
【Unity知识速递】第10期 Unity GC 零分配实战:从 UnityEngine.Pool 到手动 GC 控制的全链路优化
jvm·unity·c#·游戏引擎·lucene
时间的拾荒人9 小时前
Redis 入门详解:核心特性、重要文件与全局命令实战
开发语言·redis·面试
敲上瘾9 小时前
Qt Widgets入门:项目模板解析与Hello World
开发语言·数据库·c++·qt·ui·qt6.3
码途行者10 小时前
网站的SQL 注入:从攻击原理到防御措施
开发语言·sql·php
旖旎夜光10 小时前
【C++ 基础入门】C++ 多态(中):虚函数表、多态原理与动静绑定
开发语言·c++·笔记·学习
你看我名字10 小时前
产品参数昨天还对,今天已过期:数眼智能与大模型应用如何做资料版本校验
开发语言·架构