IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Extendible Hashing 详解 -> 正文阅读

[数据结构与算法]Extendible Hashing 详解

原文来自Extendible Hashing

Extendible Hashing是一个动态哈希算法,利用一个目录(directories)和许多buckets(类似page,页,下面统称为叶结点,叶)被用来hash映射数据。这是一种灵活的方式,hash函数,hash表都经历了动态变化。

Extendible Hashing 有两个主要的部分

  1. 目录(Directories): 即我们的哈希数组,目录的一个slot(即一个元素,下标)存储一个指向叶的地址的指针。还有一个id被分配给每个目录项,当目录扩张的时候,id就会发生改变。
  2. 叶(bucket): 桶用来存储散列后的数据(hash(key)和对应的value)

算法的组成结构(Basic Structure of Extendible Hashing):

image1

该算法主要组成部分:

  1. 目录(Directories): 用来存储指向叶的指针。每个目录项都有一个独特的id(被拆分为位运算的形式),id会在目录扩张的时候发生改变(详解在下方)。哈希函数会返回一个目录项的id,被用来导向到合适的叶节点中。目录项的总数 = 2^Global Depth;
  2. 叶(Buckets): 用来存储hash(key)。目录项会指向这些叶。叶由两部分组成
    • 头节点(header): 用来存储Local Depth。
    • 记录(tuple): 叶结点中包含了多个指针,用来存储数据:hash(key)和value
  3. 全局计数器(Global Depth): 和目录相关。目录项的id被表示为位运算的形式,位运算的最大可用位数 = Global Depth。通过hash(key)的前Global Depth位来找到对应的目录项,并放入对应的叶中。
  4. 局部计数器(Local Depth): 和全局计数器的概念相同,但是局部计数器和叶相关而不是和目录相关。局部计数器 = max(1,最后一次分裂时的全局计数器)。当叶发生溢出时,且局部计数器 = 全局计数器,此时目录就发生了扩张。
  5. 叶分裂(Bucket Splitting): 当叶中的元素个数超过了给定的元素个数,发生叶溢出和叶分裂(叶已经满了,仍然还要往里面插入,此时叶结点分裂,局部计数器++)。
  6. 目录扩张(Directory Expansion): 当叶结点溢出时且Local Depth = Global Depth,发生了目录扩张。

算法的工作流程(Basic Working of Extendible Hashing: ):

image13

  1. 分析数据类型: key可能有多种数据类型。integer,string,float,etc…。对于不同的数据类型,哈希映射的方式不同。
  2. 转化为二进制: 将hash(key)转化为二进制的形式,对于string来说,会考虑他的acsii码值
  3. 检查Global Depth: 检查目录的全局计数器。
  4. 目录项id转化为二进制形式: 根据Global Depth,生成 0 ~ 2^(Global Depth) - 1所有的值,例如Global Depth = 3, 此时hash(key) = 9,9转化为2进制 = 1001,我们只会看前三位,即100,通过100找到对应的目录项id
  5. 找到目录项id: 根据位运算表示的前Global位,找到对应的目录项id
  6. 插入并检查溢出: 通过找到的目录项,得到指针后,进入对应的叶,插入数据,检查是否溢出,如果溢出了,执行步骤7和8,否则的话,只需要执行9
  7. 解决溢出情况: 许多情况下,在叶中插入一个数据,可能会发生叶的溢出。在这种情况下,需要核实的步骤来防止数据的丢失和出错。首先,检查局部计数器,分为两种情况进行讨论
    • 局部计数器 = 全局计数器: 那么将发生 页面扩张 和 叶分裂。让 全局计数器++ 和 局部计数器++,重新分配页目录指针(这里重新分配是局部的,只会重新分配出现叶溢出的部分,在实例中分析。)
    • 局部计数器 < 全局计数器: 让局部计数器++,并且重新分配页目录指针
      image133
  8. 重新哈希映射叶元素: 局部重新构建。将发生溢出的叶结点中的元素,全部重新hash映射,并分配到对应的叶结点中。只对于发生溢出的才需要重新构建,没有发生溢出的叶不会发生改变,
  9. 所有元素重新哈希完毕。

实例

这个实例来自于cmu15-445的课上案例。

image14

此时global = 2,插入A,A的前两位 = 01,因此插入到01对应的叶结点中。

image15

global = 2,插入B,B的前两位 = 10,因此插入到10对应的叶结点中。

image16

global = 2,插入C,C的前两位 = 10,因此插入到10对应的叶结点中,可以看到此时发生了叶溢出,global = local,所以需要 目录扩张 + 叶分裂

image17

我们只需要重新构建发生溢出的叶结点,原来的叶结点变为两个,其中100,101分配映射到两个不同的叶结点,这时候就可以插入C了(如果此时还发生溢出,就需要继续分裂)

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:44:27  更:2022-05-05 11:47:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:49:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码