zoukankan      html  css  js  c++  java
  • 散列表

    散列表


    引言

    查找也叫检索,是根据给定的某个值,在表中确定一个关键字等于给定值的记录或数据元素;关键字,是数据元素中某个数据项的值,它可以标识一个数据元素(主关键字和次关键字)。(比如在一个学生信息的记录中,给出的关键字是学生的学号,我要查找这个学生的信息记录,这就是查找的一个具体应用

    查找方法的评价指标有如下几个

    • 查找速度
    • 占用存储空间多少
    • 算法本身复杂程度
    • 平均查找长度ASL(Average Search Length): 为确定记录在表中的位置,需将关键字和给定值进行比较的平均次数

    在查找过程中时间主要消耗在了关键字值的比较上,可不可以不经过关键字间的比较就找到对应的存储位置呢?换句话说就是在待查记录的关键字与它的存储位置之间建立一个确定的对应关系,则查找就可以不必再进行关键字值间的比较。如下图所示,就可以通过给定的关键字值直接通过哈希函数计算出对应额存储位置,这样就避免了一一比较的过程。

    这里写图片描述
    但是要求关键字值和存储地址要一一对应的!但并不是每次都有那么好的运气,能构造出理想的哈希函数。如下面采用的哈希函数,造成了冲突。
    这里写图片描述
    由上面的分析,可以得出哈希表的概念(哈希表,即是散列表)
    根据设定的哈希函数及处理冲突的方法将查找表中各数据元素存储在一段有限的连续空间中,即得哈希表。


    基本概念

    散列的基本思想:在记录的存储地址和它的关键码之间建立一个确定的对应关系。这样,不经过比较,一次读取就能得到所查元素的查找方法。
    散列表:采用散列技术将记录存储在一块连续的存储空间中,这块连续的存储空间称为散列表。
    散列函数:将关键码映射为散列表中适当存储位置的函数。
    散列地址:由散列函数所得的存储位置
    这里写图片描述

    散列的查找技术

    问:散列技术仅仅是一种查找技术吗?
    散列既是一种查找技术,也是一种存储技术。
    问:散列是一种完整的存储结构吗?
    散列只是通过记录的关键码定位该记录,没有完整地表达记录之间的逻辑关系,所以,散列主要是面向查找的存储结构。

    散列技术的关键问题:

    ⑴ 散列函数的设计。如何设计一个简单、均匀、存储利用率高的散列函数。
    ⑵ 冲突的处理。如何采取合适的处理冲突方法来解决冲突。

    冲突:对于两个不同关键码ki≠kj,有H(ki)=H(kj),即两个不同的记录需要存放在同一个存储位置,ki和kj相对于H称做同义词

    散列函数

    设计散列函数一般应遵循以下原则:
    ⑴ 计算简单。散列函数不应该有很大的计算量,否则会降低查找效率。
    ⑵ 函数值即散列地址分布均匀。函数值要尽量均匀散布在地址空间,这样才能保证存储空间的有效利用并减少冲突。

    散列函数——直接定址法

    这里写图片描述

    散列函数——除留余数法

    这里写图片描述

    散列函数——数字分析法

    根据关键码在各个位上的分布情况,选取分布比较均匀的若干位组成散列地址。
    这里写图片描述
    适用情况: 能预先估计出全部关键码的每一位上各种数字出现的频度,不同的关键码集合需要重新分析。

    散列函数——平方取中法

    这里写图片描述

    散列函数——折叠法

    这里写图片描述

    处理冲突的方法

    处理冲突的方法——开放定址法

    由关键码得到的散列地址一旦产生了冲突,就去寻找下一个空的散列地址,并将记录存入。用开放定址法处理冲突得到的散列表叫闭散列表。
    如何寻找下一个空的散列地址?
    (1)线性探测法
    当发生冲突时,从冲突位置的下一个位置起,依次寻找空的散列地址。
    这里写图片描述
    用线性探测法构造的散列表中查找算法——伪代码

    1. 计算散列地址j;
    2. 若ht[j]=k,则查找成功,返回记录在散列表中的下标;
    3. 若ht[j]为空或将散列表探测一遍,则查找失败,转4;
      否则,j指向下一单元,转2;
    4. 若整个散列表探测一遍,则表满,抛出溢出异常;
      否则,将待查值插入;

    (2)二次探测法
    这里写图片描述
    这里写图片描述
    (3)随机探测法
    当发生冲突时,下一个散列地址的位移量是一个随机数列,即寻找下一个散列地址的公式为:

    Hi=(H(key)+di)

    (di是一个随机数列,i=1,2,……,m-1)
    计算机中产生随机数的方法通常采用线性同余法,
    这里写图片描述

    其中,d称为随机种子。当b、c和m的值确定后,给定一个随机种子,产生确定的随机数序列。

    处理冲突的方法——拉链法(链地址法)

    基本思想:将所有散列地址相同的记录,即所有同义词的记录存储在一个单链表中(称为同义词子表),在散列表中存储的是所有同义词子表的头指针。
    用拉链法处理冲突构造的散列表叫做开散列表。
    设n个记录存储在长度为m的散列表中,则同义词子表的平均长度为n / m。
    这里写图片描述
    在拉链法构造的散列表查找算法——伪代码

    1. 计算散列地址j;
    2. 在第j个同义词子表中顺序查找;
    3. 若查找成功,则返回结点的地址;
      否则,将待查记录插在第j个同义词子表的表头。

    处理冲突的方法——公共溢出区

    基本思想:散列表包含基本表和溢出表两部分(通常溢出表和基本表的大小相同),将发生冲突的记录存储在溢出表中。查找时,对给定值通过散列函数计算散列地址,先与基本表的相应单元进行比较,若相等,则查找成功;否则,再到溢出表中进行顺序查找。
    这里写图片描述

    散列查找的性能分析

    由于冲突的存在,产生冲突后的查找仍然是给定值与关键码进行比较的过程。
    在查找过程中,关键码的比较次数取决于产生冲突的概率。而影响冲突产生的因素有:

    (1)散列函数是否均匀
    (2)处理冲突的方法
    (3)散列表的装载因子 α=表中填入的记录数/表的长度

    几种不同处理冲突方法的平均查找长度
    这里写图片描述

    开散列表与闭散列表的比较
    这里写图片描述


    2015-9-16 艺少

  • 相关阅读:
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Arctic Network POJ
    Truck History POJ
    QS Network ZOJ
  • 原文地址:https://www.cnblogs.com/huty/p/8519167.html
Copyright © 2011-2022 走看看