数据结构之查找运算

Deadly 提交于 2019-12-20 07:26:38

查找

  • 查找表可分为两类
  1. 静态查找表
    仅作查询和检索操作的查找表。
  2. 动态查找表
    有时在查询之后,还需要将“查询”结果为“不在查找表中”的数据元素插入到查找表中;或者,从查找表中删除其“查询”结果为“在查找表中”的数据元素。
  • 关键字
    是数据元素(或记录)中某个数据项的值,用以标识(识别)一个数据元素(或记录)。
    若此关键字可以识别唯一的一个记录,则称之谓“主关键字”。
    若此关键字能识别若干记录,则称
    之谓“次关键字”。

线性表的查找

顺序查找(都是从后往前找)

顺序查找方法既适用于线性表的顺序存储结构,又适用于线性表的链式存储结构。(无序
时间复杂度为O(n)。
在不等概率查找的情况下,ASLss 在
Pn≥Pn-1≥···≥P2≥P1时取极小值
若查找概率无法事先测定,则查找过程采取的改进办法是,在每次查找之后,将刚刚查找到的记录直接移至表尾的位置上。

折半查找(二分查找)

折半查找要求线性表必须才用顺序存储结构,而且表中元素按关键字有序排列。
时间复杂度为O(log2 n)。
算法步骤:

  1. 置查找区间初值,low为1,high为表长。
  2. 当low小于等于high时,循环执行以下操作:
  • mid取值为low和high的中间值;
  • 将给定值key和中间位置记录的关键字进行比较,若相等则查找成功,返回中间位置mid;
  • 若不相等则利用中间位置记录将表分为前后两个字表。如果key比中间位置记录的关键字小,则high取mid-1,否则low取为mid+1。
  1. 循环结束,说明查找区间为空,则查找失败,返回0。

分块查找(索引顺序查找)

索引顺序表=索引+顺序表,一般情况下,索引是一个有序表
分块有序,即分成若干子表,要求每个子表中的数值都比后一块中数值小(但子表内部未必有序)。
然后将各子表中的最大关键字构成一个索引表,表中还要包含每个子表的起始地址(即头指针)
分块查找过程:

  1. 对索引表使用折半查找法(因为索引表是有序表);
  2. 确定了待查关键字所在的子表后,在子表内采用顺序查找法(因为各子表内部是无序表);

数表的查找

  • 这里暂时不做过多解释… …

哈希表(散列表的查找)

  • 对于动态查找而言,(1)表长不确定;(2)在设计查找表时,只知道关键字所属范围,而不知道确切的关键字。
  • 因此在一般情况下,需要关键字于记录在表中的存储位置之间建立一个函数关系,以 f(key) 作为关键字为 key 的记录在表中的位置,通常称这个函数 f(key) 为哈希函数(散列函数)。
  • 简单地说,哈希表(散列表)是基于哈希函数(散列函数)建立的一种查找表。
  1. 哈希表的定义:
    根据设定的哈希函数 H(key) 和所选中的处理冲突的方法,将一组关键字映象到一个有限的、地址连续的地址集 (区间) 上,并以关键字在地址集中的“象”作为相应记录在表中的存储位置,如此构造所得的查找表称之为“哈希表

  2. 散列函数的构造方法

  • 直接定址法
    哈希函数为关键字的线性函数
    H(key) = key 或者
    H(key) = a * key + b
  • 数字分析法
    假设关键字集合中的每个关键字都是由 s 位数字组成 (u1, u2, …, us),分析关键字集中的全体, 并从中提取分布均匀的若干位或它们的组合作为地址。
    此方法仅适合于:能预先估计出全体关键字的每一位上各种数字出现的频度。
  • 平方取中法
    以关键字的平方值的中间几位作为存储地址。求“关键字的平方值” 的目的是“扩大差别” ,同时平方值的中间各位又能受到整个关键字中各位的影响。
    此方法适合于: 关键字中的每一位都有某些数字重复出现频度很高的现象。
  • 折叠法
    将关键字分割成若干部分,然后取它们的叠加和为哈希地址。有两种叠加处理的方法:移位叠加间界叠加
    此方法适合于: 适合于散列地址的位数较少,而关键字的位数较多,且难于直接从关键字中找到取值较为分散的几位。
  • 除留余数法(最常用)
    设定哈希函数为:
    H(key) = key MOD p
    其中, p≤m (表长) 并且p且为质数
  • 随机数法
    设定哈希函数为:
    H(key) = Random(key)
    其中,Random 为伪随机函数
    通常,此方法用于对长度不等的关键字构造哈希函数。
  1. 处理冲突的方法
  • 开放定址法
    a. 线性探测再散列 di = 1,2,3,…,m-1 且di=i
    b.平方探测再散列 di = 12, -12, 22, -22, …,+k2, -k2(K<=m/2)
    c.随机探测再散列 di 是一组伪随机数列 或者
    di=i×H2(key) (又称双散列函数探测)
    线性探测法的特点
    优点:只要哈希表未被填满,保证能找到一个空地址单元存放有冲突的元素。
    缺点:会产生“二次聚集”现象,降低查找效率.
    二次探测法和伪随机探测法的的特点
    优点: 可以避免“二次聚集”现象
    缺点:不能保证一定找到不发生冲突的地址。
    开放地址法建立哈希表的步骤
    step1 取数据元素的关键字key,计算其哈希函数值(地址)。若该地址对应的存储 空间还没有被占用,则将该元素存入;否则执行step2解决冲突。
    step2 根据选择的冲突处理方法,计算关键字key的下一个存储地址。若下一个存储地址仍被占用,则继续执行step2,直到找 到能用的存储地址为止。

  • 链地址法
    相同哈希地址的记录链成一单链表,m个哈希地址就设m个单链表,然后用用一个数组将m个单链表的表头指针存储起来,形成一个动态的结构
    链地址法建立哈希表的步骤:
    step1 取数据元素的关键字key,计算其哈希函数值(地址)。若该地址对应的链表为空,则将该元素插入此链表;否则执行step2解决冲突。
    step2 根据选择的冲突处理方法,若该地址对应的链表为不为空,则利用链表的前插法或后插法将该元素插入此链表。

  1. 哈希表的查找
    查找过程和造表过程一致。假设采用开放定址处理冲突,则查找过程为:
    a.对于给定值 K, 计算哈希地址 i = H(K)
    b.若 r[i] = NULL 则查找不成功
    c.若 r[i].key = K 则查找成功
    d.否则 “求下一地址 Hi” ,直至 r[Hi] = NULL (查找不成功)或 r[Hi].key = K (查找成功) 为止。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!