数据结构08查找

第九章 查找

另一种在实际应用中大量使用的数据结构--查找表。

所谓查找,即为在一个含有众多的数据元素的查找表中找出某个“特定的”数据元素。

 

查找表 search table 是由同一类型的数据元素构成的集合。集合中的数据元素之间存在着完全松散的关系,故查找表非常灵便。

 

对查找表经常进行的操作:

>查询某个元素是否在查找表中;

>检索某个元素的各种属性;

>插入

>删除

 

静态查找表 static search table:只包含查询和检索。

动态查找表 dynamic search table:包含查询、检索、插入、删除。

 

关键字 Key 用于标识数据元素。

>主关键字 primary key:唯一的标识一个记录。

>次关键字 secondary key:识别若干记录。

 

查找 searching:

根据给定的某个值,在查找表中确定一个其关键字等于给定值的记录。

 

由于表中数据元素之间仅存在“同属一个集合”的松散关系,需在数据元素之间人为的加上一些关系,以便按某种规则进行查找,即以另一种数据结构来表示查找表。

>静态查找表

>动态查找表

 

9.1 静态查找表

静态查找表有不同的表示方法,在不同的表示方法中,实现查找操作的方法也不同。

 

9.1.1 顺序表的查找

以顺序表或线性链表表示静态查找表,则可用顺序查找来实现。

顺序查找 sequential search

从表中最后一个记录开始,逐个进行记录关键字和给定值的比较,若相等,则查找成功;反之,直到第一个记录都不相等,则表明表中没有要查找的记录,查找不成功。

 

Tip:在查找尾端设置哨兵,而免去每一步都要检测整个表是否查找完毕,可节约一半的时间。哨兵的值等于所查找的关键字。

 

查找表性能度量:平均查找长度(Average Search Length)ASL

 


对记录的查找概率不相等的查找表,若能预先得知每个记录的查找概率,则应先对记录的查找概率进行排序,使表中记录按查找概率由小到大重新排列,以便提高查找效率。

在一般情况下,记录的查找概率预先无法测定。

为了提高查找效率,可以在每个记录中附设一个访问频度域,并使顺序表中的记录保持按访问频度非递减有序排列,使得查找概率大的记录在查找过程中不断后移,以便在以后的逐次查找中减少比较次数。

或者在每次查找之后都将刚查找到的记录直接移至表尾。

 

顺序查找:

缺点:平均查找长度较长,当n很大时,查找效率低。

优点:简单且适应面广,对表结构无任何要求,无论记录是否按关键字有序均可应用。

 

 

 

9.1.2 有序表的查找

 

折半查找 binary search:

先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或找不到该记录为止。

 

折半查找性能:

对任意的n,当n>50时,有下列近似结果

 

折半查找只适用于有序表,且限于顺序存储结构,对线性链表无法有效地进行折半查找。

 

 

Fibonacci查找:

根据Fibonacci序列的特点对表进行分割。

开始时,表中记录个数比某个Fibonacci数小1,即

 

Fibonacci查找的平均性能比折半查找好,但最坏情况下的性能(虽然仍是O(logn))比折半查找差。

另一个优点,分割时只需进行加减运算。

 

插值查找:

根据给定值key来确定进行比较的关键字位置i的查找方案。

公式:

 

其中,high和low为最大关键字和最小关键字的下标。

插值查找只适合于关键字均匀分布的表。在这种情况下,对表长较大的顺序表,其平均性能比折半查找好。

 

9.1.3 静态树表的查找

当有序表中各记录的查找概率不等时,折半查找性能未必最优。

描述查找过程的判定树为何类二叉树时,其查找性能最佳?

如果只考虑查找成功的情况,则查找性能最佳的判定树是其带权内路径长度之和PH值取最小值的二叉树。

称PH值最小的二叉树为静态最优查找树(Static Optimal Search Tree)。

构造静态最优查找树花费的时间代价高。

 

静态树表是把有序的静态查找表根据数据被查找的概率生成一棵二叉树。

 

介绍一种构造近似最优查找树的有效算法。

次优查找树(Nearly Optimal Search Tree):带权内路径长度PH值在所有具有同样权值的二叉树中近似为最小。

方法:选取第i个记录作为根结点,然后分别对左右序列构造两个次优查找树作为i的左右子树。

i满足的条件:左序列权值和右序列权值之和差值的绝对值最小。

 

由于在构造次优查找树的过程中,没有考察单个关键字的相应权值,则有可能出现被选为根的关键字的权值比与它相邻的关键字的权值小。此时应作适当调整:选取邻近的权值较大的关键字作次优查找树的根结点。

例:关键字 A  B   C  D  E

    权值   1  30  2  29  3

大量的实验研究表明,次优查找树和最优查找树的查找性能之差仅为1%~2%,很少超过3%。

且构造次优查找树的算法的时间复杂度为O(nlogn)。

 

 

9.1.4 索引顺序表

有点像Skip List。

分块查找又称索引顺序查找,这是顺序查找的一种改进方法。

除表本身外,还需建立一个“索引表”。

索引表按关键字有序,表或者有序或者分块有序。

分块查找过程需分两步进行:先确定待查记录所在的块(子表),然后在块中顺序查找。

 

由于索引表按关键字有序,则确定块的查找可以用顺序查找,亦可用折半查找。而块中记录是任意排列的,则在块中只能是顺序查找。

分块查找是顺序查找和折半查找的简单结合。

若都用顺序,

 

9.2 动态查找表

表结构支持插入和删除操作。

9.2.1 二叉排序树和平衡二叉树

二叉排序树(Binary Sort Tree)或者是一棵空树,或者是具有下列性质的二叉树:

(1)若左子树不空,则左子树上所有结点均小于根结点;

(2)若右子树不空,则右子树上所有结点均大于根结点;

(3)左右子树均为二叉排序树。

 

 

二叉排序树又称二叉查找树。

中序遍历二叉排序树可得到一个关键字的有序序列。

即一个无序序列可以通过构造一棵二叉排序树而变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。

 

插入:每次插入的新结点都是二叉排序树上新的叶子结点。

删除:  

  1. 若删除点无孩子结点,直接删除;
  2. 若删除点只有一个孩子,则将其孩子替代其位置;
  3. 若删除点有两个孩子,两种方法:
    a) 链上左孩子,右孩子为左孩子的最右;或链上右孩子,左孩子为右孩子最左;
    b) 用直接前驱替代,然后删掉直接前驱;或用直接后继替代,然后删掉直接后继。

 

 

平衡二叉树(Balanced Binary Tree 或 Height-Balanced Tree)或者是一棵空树,或者是具有如下性质的二叉树:

它的左右子树都是平衡二叉树,且左右子树的深度之差的绝对值不超过1。

 

平衡因子BF(Balance Factor):该结点左子树的深度减去右子树的深度。

平衡二叉树所有结点的平衡因子只可能是-1,0,1。

只要二叉树上有一个结点平衡因子的绝对值大于1,则该二叉树就是不平衡的。

 

在平衡二叉排序树BBST上插入一个新的数据元素e的递归算法如下:

  1. 若BBST为空树,则插入一个数据元素为e的新结点作为BBST的根结点,树的深度增1;
  2. 若e的关键字和BBST的根结点的关键字相等,则不进行插入;
  3. 若e的关键字小于BBST的根结点的关键字,而且在BBST的左子树中不存在和e有相同关键字的结点,则将e插入在BBST的左子树上,并且当插入之后的左子树深度加1时,分别就下列不同情况处理之:

    a) BBST的根结点的平衡因子为-1,则将根结点的平衡因子更改为0,BBST的深度不变; 
    b) BBST的根结点的平衡因子为0,则将根结点的平衡因子更改为1,BBST的深度增1;
    c) BBST的根结点的平衡因子为1:
            若BBST的左子树根结点的平衡因子为1,则需进行单向右旋平衡处理,并且在右旋处理之后,将根结点和其右子树根结点的平衡因子更改为0,树的深度不变;
            若BBST的左子树根结点的平衡因子为-1,则需进行先向左、后向右的双向旋转平衡处理,并且在旋转处理之后,修改根结点和其左右子树根结点的平衡因子,树的深度不变;
     
  4. 若e的关键字大于BBST的根结点的关键字,而且在BBST的右子树中不存在和e有相同关键字的结点,则将e插入在BBST的右子树上,并且当插入之后的右子树深度增加1时,分别就不同情况处理之。其处理操作和步骤3中所述相对称。

  

LL型:新结点Y插入到A的左子树的左子树上   左左->右

 

RR型:新结点Y插入到A的右子树的右子树上   右右->左

 

LR型:新结点Y插入到A的左子树的右子树上   左右->左右

                        

 

RL型:新结点Y插入到A的右子树的左子树上   右左->右左

 

                             

AVL树的平衡化处理:通过调换根结点,使左右子树的深度相等。
在一棵AVL树上插入结点可能会破坏树的平衡性,需要平衡化处理恢复平衡,且保持BST的结构性质。

若用Y表示新插入的结点,A表示离新插入结点Y最近的,且平衡因子变为2的祖先结点。

可用4种旋转进行平衡化处理:

>LL型:新结点Y插入到A的左子树的左子树上   左左->右

>RR型:新结点Y插入到A的右子树的右子树上   右右->左

>LR型:新结点Y插入到A的左子树的右子树上   左右->左右

>RL型:新结点Y插入到A的右子树的左子树上   右左->右左

 

4种不平衡情况经调整都有如下特性:

  1. 成为A型,调整前的中值结点成为新的根结点,其平衡因子为0,其左、右孩子分别是小值、大值结点;
  2. 调整后,树的深度和插入结点前一样。

特性2说明,如果插入一个结点导致平衡二叉树失衡,则只需在通向根结点的路径上进行一次平衡调整。

 

 

9.2.2 B-树和B+树

磁盘查找

 

 

 

高为h的B-树的最大结点数:

 

 

设m阶B-树的高为h,失败结点位于h+1层,则关键字个数N最少到达多少?

11结点

22结点

3结点

h结点

若树中关键字有N个,则失败结点数为N+1。

即:

给定m和N可以求出最大高度:m=199,N=1,999,999,可得h<=4;

给定m和h可以求出最少关键字数:m=3,h=4,N>=15。

 

m的选择:查找关键字所用时间最少。

两部分时间:从磁盘读入结点所需时间,在结点中查找关键字所需时间。

在B-树上进行查找的过程是一个顺指针查找结点在结点的关键字中进行查找交叉进行的过程。

 

 

在含有N个关键字的B-树上进行查找时,从根节点到关键字所在结点的路径上涉及的结点数不超过

 

插入过程为自底向上分裂结点。

每次插入首先在最低层的某个非终端结点中添加一个关键字,如果该结点的关键字个数不超过m-1,则插入完成;否则分裂。

B树索引,关键字后跟的是文件地址信息。

 

删除,若不是最后一层非终端结点,则将其用左子树的最右或者右子树的最左来替换。然后删除用于替换的结点。

否则分4种情况:

1、最后一层非终端结点,且为根结点,直接删;

2、最后一层非终端结点,不为根结点。

 

B-树主要用作文件的索引,因此它的查找涉及外存的存取。

查找包括两步:1、在B-树中找结点(磁盘);2、在结点中找关键字(内存)。

即,在磁盘上找到结点后,将其读入内存,再在内存中进行关键字的查找。

 

 

 

B+树:B-树的一种变形。

差异:

1、含k个关键字的结点必有k个子树;

2、非终端结点仅具有索引作用,与记录有关的信息均存放在叶结点中;

3、叶结点依关键字自小而大顺序链接。

 

两个头指针:一个指向根结点,另一个指向关键字最小的叶子结点。

两种查找方式

1、沿着根结点随机查找;

2、从最小关键字结点顺序查找。

 

9.2.3 键树

键树又称数字查找树(Digital Search Tree):

它是一棵度大于等于2的树,树中的每个结点只含有组成关键字的符号。

若关键字是数值,则结点中只包含一个数位;若关键字是单词,则结点中只包含一个字母字符。

 

两种存储方式:1、孩子兄弟链;2、多重链表。

 

9.3 哈希表

9.3.1 什么是哈希表

前述查找结构中,关键字和相对存储位置是随机的,在查找过程中需要进行比较,是建立在比较基础上。

冲突(collision):哈希值相同。

同义词(synonym):哈希值冲突的关键字。

一般情况下,冲突只能尽可能减少,而不能完全避免。

 

哈希表:根据设定的哈希函数H(key)和处理冲突的方法将一组关键字映像到一个有限的连续的地址集(区间)上,并以关键字在地址集中的像作为记录在表中的存储位置,这种表便称为哈希表

这一映像过程称为散列,所得存储位置称为哈希地址散列地址

 

9.3.2 哈希函数的构造方法

好的哈希函数:对于关键字集合,经哈希函数映像到地址集合中任何一个地址的概率是相等的,则称此类哈希函数为均匀的(Uniform)哈希函数

即使关键字经过哈希函数得到一个“随机的地址”,以便使一组关键字的哈希地址均匀分布在整个地址区间中,从而减少冲突。

1、直接定址法

取关键字或关键字的某个线性函数值为哈希地址:

 

2、除留余数法

 

9.3.3 处理冲突的方法

1、开放定址法

 

2、再哈希法

对冲突的关键字用另一个哈希函数计算地址,直至不再冲突。

 

3、链地址法

 

4、建立一个公共溢出区

将冲突的关键字全部加入这个缓冲区中。

 

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

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

相关文章

下载Centos7 64位镜像

下载Centos7 64位镜像 1.打开Centos官网 打开Centos官方网站地址&#xff1a;https://www.centos.org/&#xff0c;点击Get CentOS Now 2.点击Minimal ISO镜像 Minimal ISO镜像&#xff0c;与DVD ISO镜像的差别有很多&#xff0c;这里只说两点 1.Minimal ISO类似于Windows的纯净…

Scala01入门

第1章 可伸展的语言 Scala应用范围广&#xff0c;从编写脚本&#xff0c;到建立大型系统。 运行在标准Java平台上&#xff0c;与Java库无缝交互。 更能发挥力量的地方&#xff1a;建立大型系统或可重用控件的架构。 将面向对象和函数式编程加入到静态类型语言。 在Scala中&a…

Java网络01基本网络概念

协议 Protocol&#xff1a;明确规则 &#xff08;1&#xff09;地址格式&#xff1b; &#xff08;2&#xff09;数据如何分包&#xff1b; ... TCP/IP四层模型&#xff1a; 应用层 HTTP SMTP POP IMAP 传输层 TCP UDP 网际层 IP 主机网络层 host to host layer 数模、…

Java网络02基本Web概念

URI Uniform Resource Identifier 同一资源标识符 以特定语法标识一个资源的字符串 绝对URI&#xff1a;URI模式模式特有部分 scheme:scheme-specific-part scheme分为&#xff1a; data file本地文件系统 ftp http telnet urn 统一资源名 scheme-specific-part为&am…

解决自建ca认证后浏览器警告

前一篇讲解了基本的建立证书的过程&#xff0c;但是建立后总是会在浏览器那里警告&#xff1a; 此链接不是私密链接 --谷歌浏览器 此证书颁发机构不可信 此证书不是这个网站的 --ie浏览器 总之证书是生成成功了&#xff0c;但是其中的内容填写错误了&a…

Java网络03流

网络程序所做的很大一部分工作只是输入和输出&#xff1a;从一个系统向另一个系统移动数据。 输出流 Java的基本输出流类是java.io.OutputStream: public abstract class OutputStream 这个类提供了写入数据所需的基本方法&#xff0c;包括&#xff1a; public abstract vo…

基于微信小程序开发的仿微信demo

(本文参考自github/liujians,地址:https://github.com/liujians/weApp) 作者声明&#xff1a; 基于微信小程序开发的仿微信demo 整合了ionic的样式库和weui的样式库 使用请查看使用必读! 更新日志请点击这里 目前功能 查看消息 网络请求获取数据&#xff08;download示例server…

解决idea 中web项目无法正常显示的问题

转载于:https://www.cnblogs.com/nulijiushimeili/p/10575364.html

分享一个前后端分离的web项目(vue+spring boot)

Github地址&#xff1a;https://github.com/smallsnail-wh 前端项目名为wh-web后端项目名为wh-server项目展示地址为我的github pages&#xff08;https://smallsnail-wh.github.io&#xff09;用户名&#xff1a;admin&#xff0c;密码admin&#xff08;第一次启动会比较慢&am…

部署php项目到linux

服务器&#xff1a;39.106.26.67rootBayou2009 数据库&#xff1a;rootbayou2009 项目文件夹路径&#xff1a;/home/www/项目文件夹名称&#xff1a;education.bayou-tech.cn 绑定域名&#xff1a;education.bayou-tech.cn 绑定域名&#xff1a; 用ftp把配置文件下班到windows修…

ZooKeeper安装配置

配置 1、在conf目录下创建一个配置文件zoo.cfg tickTime2000 dataDir.../zookeeper/data dataLogDir.../zookeeper/dataLog clientPort2181 initLimit5 syncLimit2 server.1server1:2888:3888 server.2server2:2888:3888 server.3server3:2888:3888 •tickTime&#…

ionic2开发的仿外卖点餐系统(Ionic2+Angular2

github上的项目源码 Run this Project&#xff08;运行该项目&#xff09; first&#xff08;首先&#xff09;: make sure your computer install ionic 确保你的电脑安装了ionic2,不懂自行百度 second&#xff08;其次&#xff09;:$ ionic start wechat_restaurant tutorial…

node搭建服务器,写接口,调接口,跨域

刚开始学node&#xff0c;今天做这个也是累死宝宝了&#xff0c;以后可以自己写接口自己用了&#xff0c;再也不用麻烦人家后台人员了&#xff0c;这些年我们欠他们的太多了&#xff0c;说多了都是泪&#xff0c;不多说&#xff0c;往下看吧。。。 服务端项目目录下&#xff1a…

ThreadPoolExcutor 线程池 异常处理 (上篇)

前言 最近看到crossoverJie的一篇文章&#xff1a;一个线程罢工的诡异事件 首先感谢原作者的分享&#xff0c;自己获益匪浅。然后是回想到自己的一次面试经历&#xff0c;面试官提问了线程池中的线程出现了异常该怎样捕获&#xff1f;会导致什么样的问题&#xff1f; 示例代码 …

ionic3 调用本地相册并上传图片

前言在APP中启动相册选择器或者拍照上传图片这些功能是非常常见的。对于Ionic2&#xff0c;我们只能通过cordova插件实现调用原生的功能。下面将简单的封装一个选择相册或拍照上传图片的ImgService服务。具体如下。 Cordova准备下载安装所需的Cordovar插件&#xff1a; Image P…

Mapreduce中maptask过程详解

一、Maptask并行度与决定机制 1.一个job任务的map阶段的并行度默认是由该任务的大小决定的&#xff1b; 2.一个split切分分配一个maprask来并行处理&#xff1b; 3.默认情况下&#xff0c;split切分的大小等于blocksize大小&#xff1b; 4.切片不是mapper类中对单词的切片&…

angularjs 上传

xxx.module.ts模块 import { NgModule} from “angular/core”; import { FileUploadModule } from “ng2-file-upload” ; import { XXXComponent } from “./xxx.component”; NgModule({ imports:[ FileUploadModule ], declarations:[ XXXComponent &#xff0c;/component…

PHPCMS的产品筛选功能

如下图所示功能&#xff1a; 首先&#xff0c;用下面这些代码替换掉phpcms/libs/functions/extention.func.php的内容 <?php /*** extention.func.php 用户自定义函数库** copyright (C) 2005-2010 PHPCMS* license http://www.phpcms.cn/licen…

程序员自身价值值这么多钱么?

xx 网络公司人均奖金 28 个月…… xx 科技公司人均奖金 35 个月…… 每到年底&#xff0c;这样的新闻在互联网业内简直是铺天盖地。那些奖金不高的程序员们一边羡慕嫉妒&#xff0c;一边暗暗比较一下自己的身价&#xff0c;考虑是不是该跳槽了。 不同水平的程序员&#xff0c;薪…

Spring MVC中使用 Swagger2 构建Restful API

0.Spring MVC配置文件中的配置[java] view plaincopy<!-- 设置使用注解的类所在的jar包&#xff0c;只加载controller类 --> <span style"white-space:pre"> </span><context:component-scan base-package"com.jay.plat.config.contro…