【数据管理】谈谈哈希原理和散列表

news2024/9/25 7:22:38

一、说明

        提起哈希,有人要说:不就是一个稀疏表格么,谈的上什么原理?我说:非也,哈希是是那种看似无物,其实解决大问题的东西。如何提高数据管理效率?这是个问题,随着这个问题的深度接触,您就会发现,哈希是一个不错选择,而且配合哈希还有不少的操作,似乎不为人知。

二、从数据表的维护说起

2.1 数据库的插入删除

        我们知道,数据库最重要的维护不外乎key。数据库水平高低,就看你对key维护有何独到的设计。这里我们把key抽象成电话号码,且看如何维护?

        假设我们要设计一个以电话号码(作为键)存储员工记录的系统。我们希望高效地执行以下查询:

  • 插入电话号码和相应的信息。
  • 搜索电话号码并获取信息。
  • 删除电话号码和相关信息。

         我们可以想到使用如下数据结构来维护不同电话号码的信息。

  • 电话号码和记录的数组。
  • 电话号码和记录的链接列表。
  • 以电话号码为键的平衡二叉搜索树。
  • 直接访问表。 

        对于数组和链表,我们需要以线性方式搜索,这在实践中可能代价高昂。如果我们使用数组并保持数据排序,那么使用二进制搜索可以在 O(Logn) 时间内搜索电话号码,但是插入和删除操作变得昂贵,因为我们必须维护排序顺序。

        使用平衡二叉搜索树,我们得到适度的搜索、插入和删除时间。

        以上的数据维护是过去的老式想法,因为存储是昂贵的。所以,索引数据(电话号)需要密集排列,中间没有间隙。因此插入、删除、排序成了必须的维护手段。

2.2 全预留表格

        所谓哈希表的稀疏性,还不如叫做全预留表格。也就是不管你的电话号出不出现,我总是预留一个超大表格,该表格足以覆盖电话号码的全部。比如,对于电话号码,我们首先做一个00000000-99999999的大数组,该数组足以满足任意电话号码的存取,而且常驻内存。以上电话号码的哈希表如图。

电话号码的哈希表 

        这种设计看似蠢笨,然而,在现实中的内存数据库全是这种模式:用大内存换取时间。因而使得dds协议,rtps协议得以实现,比如redis数据库就是这种模式。

        如果电话号码不存在,则数组中的条目为 NIL,否则数组条目存储指向records corresponding to phone number. 时间复杂度方面这个解决方案是最好的,我们可以在 O(1) 时间内完成所有操作。例如插入一个电话号码,我们创建一个包含给定电话号码详细信息的记录,使用 phone number 作为索引,并将指向创建的记录的指针存储在表中。
        这个解决方案有很多实际限制。这个解决方案的第一个问题是需要额外的空间是巨大的。例如,如果电话号码是 n 位数字,我们需要 O(m * 10n) 表空间,其中 m 是要记录的指针的大小。问题是编程语言中的整数可能不会存储 n 位数字。

        由于上述限制,不能总是使用直接访问表。哈希是几乎可以在所有此类情况下使用的解决方案,并且在实践中与上述数据结构(如数组、链表、平衡 BST)相比表现非常出色。(1)搜索时间平均(在合理的假设下)和最坏情况下的 O(n)。现在让我们了解什么是散列。

三、为什么要使用哈希?

3.1 最简单的散列方法

        散列:散列是一种流行的技术,用于尽可能快地存储和检索数据。下面用最简单例子说明为什么要散列,如何散列?

        比如有0-200的随机数作为key键,那么,如果用全预留表格存储,索引字至少用201个存储单元(有些单元可能永远不用)。

        那么我用长度12个长度单元存索引,如下:

        Random ∈【0-200】,索引字为Index∈【0,11】,索引字数组长度L=12,模数M=11.

        Random % M = Index

给出几个具体数字:55,70,196,185,0,200

   

        我们索引一个关键字(比如196)的次数为:N = Index(最多10)+ 链表(最多18次)≤ 28次,是不是比全索引表200次要少很多呢?

3.2 更高明的哈希--平恒二叉树

        如果你仔细观察,在平衡的二叉搜索树中,如果我们尝试搜索、插入或删除任何元素,那么相同的时间复杂度是 O(logn)。以更快的方式操作,即以更优化的方式和这里的散列开始发挥作用。在散列中,所有上述操作都可以在 O(1) 中执行,即常数时间。重要的是要理解散列的最坏情况时间复杂度仍然是 O(n),但平均情况时间复杂度是 O( 1).
现在让我们了解一些散列的基本操作。

基本操作:

  • HashTable:此操作用于创建新的哈希表。
  • 删除:此操作用于从哈希表中删除特定的键值对。
  • 获取:此操作用于在哈希表中搜索键并返回与该键关联的值。
  • Put:此操作用于在哈希表中插入新的键值对。
  • DeleteHashTable:此操作用于删除哈希表

3.3 哈希组件

        1)哈希表:存储指向与给定电话号码对应的记录的指针的数组。如果没有现有电话号码的哈希函数值等于条目的索引,则哈希表中的条目为 NIL。简单来说,我们可以说哈希表是数组的推广。哈希表提供了一种功能,其中存储数据集合,以便以后在需要时很容易找到这些项目。

        2)哈希函数:将给定的大电话号码转换为实用的小整数值的函数。将给定的键转换为特定的槽索引。其主要工作是将每个可能的键映射到唯一的槽索引。如果每个键被映射到一个唯一的槽索引,那么哈希函数被称为完美哈希函数。创建一个完美的哈希函数非常困难,但我们作为程序员的工作是创建这样一个哈希函数,借助它的数量碰撞尽可能少。碰撞在前面讨论。

一个好的哈希函数应该具备以下特性:

  • 可高效计算。
  • 应该统一分配键(每个表位置每个位置的可能性相同)。
  • 应该尽量减少碰撞。
  • 应该有一个低负载因子(表中的项目数除以表的大小)。

        例如,对于电话号码,一个糟糕的哈希函数是取前三位数字。更好的函数是考虑最后三位数字。请注意,这可能不是最好的哈希函数。

        3)冲突处理:由于哈希函数为我们提供了一个大键的小数字,因此有可能两个键产生相同的值。新插入的键映射到哈希表中已被占用的槽的情况称为碰撞和以下是处理冲突的方法:

        Chaining:思想是让hash表的每个cell指向一个hash函数值相同的记录链表,Chaining简单,但需要表外额外的内存。
        开放式寻址:在开放式寻址中,所有元素都存储在哈希表本身中。每个表条目包含一条记录或 NIL。在搜索元素时,我们逐个检查表槽,直到找到所需的元素或者它是清楚该元素不在表中。

四、结论

        知道哈希原理,你就知道快速检索数据库大概是个什么东西,也大概知道,近几年大数据处理的数据库如Redis数据库如何构造。负载平恒概念,dds协议,rtps协议等,理解起来也不复杂了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/356358.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

测试2:编写测试用例的方法

2.编写测试用例的方法 7种 测试常用的方法:code review 代码静态分析、CI/CD CI–持续集成–开发成员经常集成它们的工作,尽快发现集成错误 CD–持续部署–将集成后的代码部署到更贴近真实运行的环境 2.1 测试用例的描述: 用例编号 用例…

Python纯Numpy手撕SGD

文章目录简介问题建模数据加载和预处理数据加载预处理分batch损失函数训练运行简介 本博客用多元线性回归展示如何从零实现一个随机梯度下降SGD, 不使用torch等AI框架 问题建模 给定一个数据集X∈RN(D1)\large X \in \R^{N \times (D1)}X∈RN(D1)和对应标签向量Y∈RN\large …

centos7防火墙工具firewall-cmd使用

centos7防火墙工具firewall-cmd使用防火墙概述centos7防火墙工具firewall-cmd使用介绍firewalld的基本使用服务管理工具相关指令配置firewalld-cmd防火墙概述 防火墙是可以帮助计算机在内部网络和外部网络之间构建一道相对隔绝的保护屏障,从而保护数据信息的一种技…

Vulnhub 渗透练习(七)—— FRISTILEAKS: 1.3

环境搭建 下载链接 virtualbox 打开靶机设置为 host-only,攻击机同样。 具体可点此处 信息收集 开了个 80 端口。 用的是 apache 2.2.15 ,这个版本有个解析漏洞。 目录 根据首页的图片猜测 /fristi/ 目录(不过我没想到 -_-&#x…

由浅入深掌握各种 Python multiprocessing 进程间通信方式

由浅入深掌握各种 Python 多进程间通信方式1、为什么要掌握进程间通信2、进程间各类通信方式简介3、消息机制通信1) 管道 Pipe 通信方式2) 消息队列Queue 通信方式4、同步机制通信(1) 进程间同步锁 – Lock(2) 子进程间协调机制 -- Event5、共享内存方式通信(1) 共享变量(2) 共…

【Python】控制自己的手机摄像头拍照,并自动发送到邮箱

前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 今天这个案例,就是控制自己的摄像头拍照, 并且把拍下来的照片,通过邮件发到自己的邮箱里。 想完成今天的这个案例,只要记住一个重点:你需要一个摄像头 思路…

Android 7.0 OTA升级(高通)

文章目录1. Full OTA 方式升级介绍1.1 Full OTA 制作第一步:生成 msm89xx-target_files-eng.XXX.zip1.2 Full OTA 制作第二步:Modem 等非 HLOS 加入升级包的方法1.3 Full OTA 制作第三步:生成 update.zip 升级包2. Incremental OTA 方式升级介…

Android 基础知识4-2.6LinearLayout(线性布局)

一、LinearLayout的概述 线性布局(LinearLayout)主要以水平或垂直方式来排列界面中的控件。并将控件排列到一条直线上。在线性布局中,如果水平排列,垂直方向上只能放一个控件,如果垂直排列,水平方向上也只能…

Java基础-xml

1.xml 1.1概述 万维网联盟(W3C) 万维网联盟(W3C)创建于1994年,又称W3C理事会。1994年10月在麻省理工学院计算机科学实验室成立。 建立者: Tim Berners-Lee (蒂姆伯纳斯李)。 是Web技术领域最具权威和影响力的国际中立性技术标准机构。 到目前为止&#…

python基础语法【自用】

✨始发站🚩Python的基础语法,冲冲冲! 🚩注:本篇为python基础语法篇,因博主之前使用java,所以本基础语法篇实为自用丐版! 🌲 你好,世界! 安装环境…

虚拟机快照

1. 快照有什么作用? 通俗理解:快照就是备份。 2. VMware Workstation 和 VMware Fusion 都支持制作快照去使用 一、快照 保存当前虚拟机状态。可以恢复 二、 在VMware Workstation Pro中制作并还原快照 三、在VMware Fusion Pro中制作并还原快照 快照制…

210天从外包踏进华为跳动那一刻,我泪目了

前言 没有绝对的天才,只有持续不断的付出。对于我们每一个平凡人来说,改变命运只能依靠努力幸运,但如果你不够幸运,那就只能拉高努力的占比。 2021年4月,我有幸成为了华为的一名高级测试工程师,正如标题所…

【软件测试】python接口自动化测试编写脚本,资深测试总结方法,你的实用宝典......

目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 接口测试&#xff0…

美团前端一面手写面试题

实现斐波那契数列 // 递归 function fn (n){if(n0) return 0if(n1) return 1return fn(n-2)fn(n-1) } // 优化 function fibonacci2(n) {const arr [1, 1, 2];const arrLen arr.length;if (n < arrLen) {return arr[n];}for (let i arrLen; i < n; i) {arr.push(arr[…

vulnhub Kioptrix4

总结&#xff1a;sql注入&#xff0c;受限shell绕过&#xff0c;mysql提权 目录 下载地址 漏洞分析 信息收集 sql注入 ssh登录绕过受限shell 提权 下载地址 Kioptrix4_Hyper_v.rar (Size: 210 MB)Download: http://www.kioptrix.com/dlvm/Kioptrix4_Hyper_v.rarDownload …

Linux驱动开发详细解析

Linux驱动开发详细解析 驱动概念 驱动与底层硬件直接打交道&#xff0c;充当了硬件与应用软件中间的桥梁。 具体任务 读写设备寄存器&#xff08;实现控制的方式&#xff09;完成设备的轮询、中断处理、DMA通信&#xff08;CPU与外设通信的方式&#xff09;进行物理内存向虚…

关于字符设备驱动的通用概念和写法

概述 设备驱动程序可以使用模块的方式动态加载到内核中去。加载模块的方式与以往的应用程序开发有很大的不同。以往在开发应用程序时都有一个 main()函数作为程序的入口点&#xff0c;而在驱动开发时却没有 main()函数&#xff0c;模块在调用 insmod 命令时被加载&#xff0c;…

JVM学习笔记一:类加载子系统

目录 前言 类加载子系统的作用 类加载器角色的位置 类加载器分类 虚拟机自带的加载器 启动类加载器&#xff08;引导类加载器&#xff09; 扩展类加载器 系统类加载器 用户自定义类加载器 什么时候需要自定义类加载器&#xff1f; 如何自定义类加载器&#xff1f; …

【验证码的识别】—— 极验验证码的识别

前言 &#xff08;结尾有彩蛋欧&#xff09; 目前&#xff0c;许多网站采取各种各样的措施来反爬虫&#xff0c;其中一个措施便是使用验证码。随着技术的发展&#xff0c;验证码的花样越来越多。验证码最初是几个数字组合的简单的图形验证码&#xff0c;后来加入了英文字母和混…

《计算机系统基础》——计算机系统导论

文章目录《计算机系统基础》——计算机系统导论计算机的基本组成程序开发与执行过程机器语言汇编语言高级语言程序的转换处理程序的数据流动计算机系统层次结构早期计算机系统1GL2GL现代计算机系统3GL4GL指令集体系结构《计算机系统基础》——计算机系统导论 &#x1f680;接下…