【王道数据结构】第七章| 查找 | 树

news2025/7/13 8:02:56

目录

一、查找

1、查找概念

2、顺序查找

3、折半查找 

4、分块查找

二、树

1、B树 

2、B树的基本操作

3、B+树

4、散列查找及其性能分析 

5、散列查找及性能分析


一、查找

1、查找概念

 

  • 查找:在数据集合中寻找满足某种条件的数据元素的过程称为查找。
  • 查找表(查找结构):用于查找的。数据集合称为查找表,它由同一类型的数据元素 (或记录)组成。
  • 关键字:数据元素中唯一标识该元素的某个数据项的值,使用基于关键字的查找,查找结果应该是唯一的。

如下举例: 

 

  • 查找长度:在查找运算中,需要对比关键字的次数称为查找长度。
  • 平均查找长度(ASL,Average Search Length): 所有查找过程中进行关键字的比较次数的平均值。

2、顺序查找

 

  • 顺序查找,又叫“线性查找”,通常用于线性表算法
  • 思想:从头到 jio 个找 (或者反过来也OK) 

代码实现: 

typedef struct{				//查找表的数据结构(顺序表)
    ElemType *elem;			//动态数组基址
    int TableLen;			//表的长度
}SSTable;

//顺序查找
int Search_Seq(SSTable ST,ElemType key){
    int i;
    for(i=0;i<ST.TableLen && ST.elem[i]!=key;++i);
    // 查找成功返回数组下标,否则返回-1
    	return i=ST.TableLen? -1 : i;
}

哨兵方式代码实现:

typedef struct{				//查找表的数据结构(顺序表)
    ElemType *elem;			//动态数组基址
    int TableLen;			//表的长度
}SSTable;

//顺序查找
int Search_Seq(SSTable ST,ElemType key){
    ST.elem[0]=key;
    int i;
    for(i=ST.TableLen;ST.elem[i]!=key;--i)
    // 查找成功返回数组下标,否则返回0
	    return i;
}

 用查找判定树分析ASL

  • 一个成功结点的查找长度=自身所在层数
  • 一个失败结点的查找长度 =其父节点所在
  • 层数默认情况下,各种失败情况或成功情况都等概率发生

3、折半查找 

【折半查找概念】

  • 折半查找,又称“二分查找”,仅适用于有序的顺序表

折半查找代码实现: 

typedef struct{
    ElemType *elem;
    int TableLen;
}SSTable;

// 折半查找
int Binary_Search(SSTable L,ElemType key){
    int low=0,high=L.TableLen,mid;
    while(low<=high){
        mid=(low+high)/2;
        if(L.elem[mid]==key)
            return mid;
        else if(L.elem[mid]>key)
            high=mid-1;					//从前半部分继续查找
        else
            low=mid+1;					//从后半部分继续查找
    }
    return -1;
}
  • 折半查找判定树的构造:m i d = ⌊ ( l o w + h i g h ) / 2 ⌋ ,如果当前 low 和 high 之间有奇数个元素,则 mid 分隔后,左右两部分元素个数相等;如果当前 low 和 high 之间有偶数个元素,则 mid 分隔后,左半部分⽐右半部分少⼀个元素。
  • 折半查找的判定树中,若m i d = ⌊ ( l o w + h i g h ) / 2 ⌋ ,则对于任何⼀个结点,必有:右⼦树结点数 - 左⼦树结点数 = 0 或 1。
  • 折半查找的判定树⼀定是平衡⼆叉树。折半查找的判定树中,只有最下⾯⼀层是不满的。因此,元素个数为 n 时树⾼ h = ⌈ l o g 2 ( n + 1 ) ⌉ 。
  • 判定树结点关键字:左<中<右,满⾜⼆叉排序树的定义。失败结点:n+1个(等于成功结点的空链域数量)
  • 折半查找的查找效率:折半查找的时间复杂度 = O ( l o g 2 n ) 。

4、分块查找

分块查找所针对的情况:块内⽆序、块间有序。


 索引表及顺序表代码

// 索引表
typedef struct{
    ElemType maxValue;
    int low,high;
}Index;

// 顺序表存储实际元素
ElemType List[100];
  • 查找目标关键字所在分块可使用顺序查找和折半查找两种方式。
  • 若使用折半查找且索引表中不包含⽬标关键字,则最终要停在 low > high,要在 low 所指分块中查找目标关键字。
  • 查找效率分析(ASL):假设⻓度为 n 的查找表被均匀地分为 b 块,每块 s 个元素。设索引查找和块内查找的平均查找⻓度分别为 ASL=LI​+LS​

二、树

1、B树 

B树,⼜称多路平衡查找树,B树中所有结点的孩⼦个数的最⼤值称为B树的阶,通常⽤m表示。⼀棵m阶B树或为空树,或为满⾜如下特性的m叉树:

  • 树中每个结点⾄多有 m 棵⼦树,即⾄多含有 m-1 个关键字。
  • 若根结点不是终端结点,则⾄少有两棵⼦树。
  • 除根结点外的所有⾮叶结点⾄少有 ⌈ m / 2 ⌉棵⼦树,即⾄少含有 $\lceil m/2\rceil-1 $个关键字。(为了保证查找效率,每个结点的关键字不能太少)
  • 所有的叶结点都出现在同⼀层次上,并且不带信息(可以视为外部结点或类似于折半查找判定树的查找失败结点,实际上这些结点不存在,指向这些结点的指针为空)。

 

m阶B树的核⼼特性:

  • 根节点的⼦树数∈ [ 2 , m ] ∈[2, m]∈[2,m],关键字数 ∈ [ 1 , m − 1 ] ∈[1, m-1]∈[1,m−1]。
  • 其他结点的⼦树数∈ [ ⌈ m / 2 ⌉ , m ] ∈[⌈m/2⌉ , m]∈[⌈m/2⌉,m];关键字数∈ [ − 1 , m − 1 ] ∈[ -1, m-1]∈[−1,m−1]。
  • 对任⼀结点,其所有⼦树⾼度都相同。
  • 关键字的值:⼦树0 < 关键字1 < ⼦树1 < 关键字2 < ⼦树2 <…. (类⽐⼆叉查找树左<中<右)

B树的⾼度:含 n 个关键字的 m叉B树,最⼩⾼度、最⼤⾼度是多少?

  • logm​n+1≤h≤log⌈m/2⌉​2n+1​+1

2、B树的基本操作

B树的查找

  • B树的查找操作与二叉查找树类似。B树的查找包含两个基本操作:① 在B树中找结点;② 在结点中找关键字。B树常存储在磁盘上,因此前一个查找操作在磁盘上进行,后一个查找操作在内存中进行。在B树中查找到某个结点后,先在有序表中进行查找,若找到则查找成功,否则按照对应指针信息到所指的子树中去查找。查找到叶子结点(对应指针为空指针),则说明树中没有对应的关键字,查找失败。

B树的插入:将关键字 key 插入到B树的过程: 

  • 定位:利用B树的查找算法,找到插入该关键字的最底层中的某个非叶子结点。(插入位置一定是最底层的某个非叶子结点!)
  • 插入:B树中,每个非失败节点的关键字个数都在区间[ ⌈ m / 2 ⌉ − 1 , m − 1 ] [⌈m/2⌉- 1,m-1][⌈m/2⌉−1,m−1]内。若插入关键字 key 之后结点关键字个数小于m,则可以直接插入;否则必须对结点进行分裂。
  • 分裂:从结点的中间位置(⌈ m / 2 ⌉ ⌈m/2⌉⌈m/2⌉)将其中的关键字分为两部分,左半部分包含的关键字放到原结点中,右半部分包含的关键字放到新节点中,中间位置(⌈ m / 2 ⌉ ⌈m/2⌉⌈m/2⌉)的关键字则插入原节点的父节点。若此时父节点的关键字也超过了上限,则对父节点继续进行分裂操作,直到这个过程传到根节点为止,进而导致B树的高度增加。

B树的删除:

  1. 非终端结点的删除:使用直接前驱或者直接后继来代替被删除的关键字,转换为删除终端结点。
  2. 终端结点的删除,具体分为三种情况
  • 直接删除关键字:若删除关键字所在结点关键字个数 ≥ ⌈ m / 2 ⌉ ≥⌈m/2⌉≥⌈m/2⌉,则可直接删除。
  • 兄弟够借:若删除关键字所在结点关键字个数 = ⌈ m / 2 ⌉ − 1 =⌈m/2⌉-1=⌈m/2⌉−1,且与此结点相邻的左(或右)兄弟结点关键字个数 ≥ ⌈ m / 2 ⌉ ≥⌈m/2⌉≥⌈m/2⌉,则需调整该节点、左(或右)兄弟结点及其双亲结点(父子换位法)以达到新的平衡。
  • 兄弟不够接:若删除关键字所在结点关键字个数 = ⌈ m / 2 ⌉ − 1 =⌈m/2⌉-1=⌈m/2⌉−1,且与此结点相邻的左(或右)兄弟结点关键字个数 = ⌈ m / 2 ⌉ − 1 =⌈m/2⌉-1=⌈m/2⌉−1,则将该节点、左(或右)兄弟结点及其双亲结点中的关键字进行合并。
     

3、B+树

一棵m阶的B+树需满足以下条件: 

  • 每个分支节点最多有m棵子树(孩子结点)。
  • 非叶根结点至少有两颗子树,其他每个分支结点至少有⌈ m / 2 ⌉ ⌈m/2⌉⌈m/2⌉棵子树。
  • 结点的子树个数与关键字个数相同。
  • 所有叶子结点包含所有关键字及指向相应记录的指针,叶子结点中将关键字按大小排列,并且相邻叶子结点按大小顺序相互链接起来。(说明B+树支持顺序查找)
  • 所有分支节点仅包含它的各个节点中关键字的最大值及指向其子节点的指针。
     

4、散列查找及其性能分析 

散列表的基本概念

  • 散列函数:一个把查找表中的关键字映射成该关键字对应的地址的函数,记作H a s h ( k e y ) = A d d r Hash(key)=AddrHash(key)=Addr。
  • 散列函数可能会把两个或两个以上的不同关键字映射到同一地址,称这种情况为冲突。发生碰撞的不同关键字称为同义词。
  • 散列表:根据关键字而直接进行访问的数据结构。散列表建立了关键字和存储地址之间的一种直接映射关系。

散列函数的构造方法

  1. 直接定址法:直接取关键字的某个线性函数值为散列地址,散列函数为 H ( k e y ) = k e y  或 H ( k e y ) = a × k e y + b 。这种方法计算简单,不会产生冲突。缺点是空位较多,会造成存储空间浪费。
  2. 除留余数法:假定散列表表长 m,取一个不大于但最接近 m 的质数 p,利用散列函数 H ( k e y ) = k e y % p将关键字转换为散列地址。p取质数是因为这样可以使关键字通过散列函数转换后等概率地映射到散列空间上的任一地址。
  3. 数字分析法:假设关键字是 r进制数,而r个数码在个位上出现的频率不一定相同,可能在某些位上分布的均匀一些,而在某些位分布的不均匀。此时应选数码分布均匀的若干位作为散列地址。
  4. 平方取中法:这种方法取关键字平方值的中间几位作为散列地址,具体取多少位视具体情况而定。这种方法得到的散列地址与关键字的每一位都有关系,因此使得散列地址分布比较均匀。适用于关键字每位取值都不够均匀或均小于散列地址所需的位数。

5、散列查找及性能分析

散列查找执行步骤如下

  1. 初始化:A d d r = H a s h ( k e y ) 
  2. 检测查找表中地址为 Addr 的位置上是否有记录,若无记录,返回查找失败;若有记录,比较它和 key 的值,若相等则返回查找成功,否则执行步骤③。
  3. 用给定的处理冲突方式计算“下一个散列表地址”,并把 Addr 置为此地址,转入步骤②。

平均查找长度(ASL):散列表查找成功的平均查找长度即找到表中已有表项的平均比较次数;散列表查找失败的平均查找长度即找不到待查的表项但能找到插入位置的平均比较次数。

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

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

相关文章

当ChatGPT遇到前端开发

目录 一、ChatGPT是什么&#xff1f; 二、怎么注册使用ChatGPT&#xff1f; 1、注册账号 2.完成 ChatGPT 手机号码验证 3、登录 ChatGPT 账号并开始使用 三、当ChatGPT遇到前端开发 四、深思总结 AIGC 作画带给人们的惊艳感觉还未散去&#xff0c;ChatGPT 又来刺激人类脆…

leetcode 困难 —— N 皇后, N皇后 II,八皇后(简单递归)

&#xff08;不知道为啥总是给这种简单的递归设为困难题&#xff0c;虽然优化部分很不错&#xff0c;但是题目太好过了&#xff09; 题目&#xff1a; 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个…

java 自定义json解析注解 复杂json解析 工具类

java 自定义json解析注解 复杂json解析 工具类 目录java 自定义json解析注解 复杂json解析 工具类1.背景2、需求-各式各样的json一、一星难度json【json对象中不分层】二、二星难度json【json对象中出现层级】三、三星难度json【json对象中存在数组】四、四星难度json【json对象…

【Selenium学习】Selenium 八大定位法

1.1 ID定位HTML Tag 的 id 属性值是唯一的&#xff0c;故不存在根据 id 定位多个元素的情况。下面以在百度首页搜索框输入文本“python”为例。搜索框的 id 属性值为“kw”&#xff0c;如图1.1所示&#xff1a;代码如下&#xff0c;“find_element_by_id”方法已废弃&#xff0…

基于nodejs+vue的健身房课程预约平台

本系统主要实现了首页、个人中心、用户管理、教练管理、会员卡管理、购买会员管理、课程类型管理、课程信息管理、课程购买管理、场地信息管理、场地预约管理、系统管理,用户&#xff1a;首页、个人中心、购买会员管理、课程购买管理、场地预约管理,教练&#xff1a;首页、个人…

睿创转债,声迅转债上市价格预测

睿创转债基本信息转债名称&#xff1a;睿创转债&#xff0c;评级&#xff1a;AA&#xff0c;发行规模&#xff1a;15.6469亿元。正股名称&#xff1a;睿创微纳&#xff0c;今日收盘价&#xff1a;47.45元&#xff0c;转股价格&#xff1a;40.09元。当前转股价值 转债面值 / 转…

树生成工具泛型接口 TreeNode

1、定义泛型接口 // 实现接口需要传入两个参数&#xff0c;第一个T 为节点中的id&#xff0c;第二个R 为节点&#xff0c;TreeNode。 public interface TreeNode<T, R extends TreeNode<T, R>> {/*** 获取节点id** return 树节点id*/T id();/*** 获取该节点的父节…

读书笔记//《数据分析:企业的贤内助》

数据分析师是个杂家——作者陈哲。 为什么写这本书&#xff1f; 懂得再多知识却不会用&#xff0c;原因是缺少通往思路、方法和技能的两条路径——项目流程和项目应用&#xff08;案例&#xff09; —————————— 数据分析师的晋升空间 &#xff08;见第2章&#xff0…

NLP模型检查英语语法错误

当NLP模型产生了语法错误&#xff0c;怎么办&#xff1f;比如&#xff0c;He wants that you send him an email.没关系&#xff0c;现在可以像小时候的英语老师&#xff0c;改作文一样简单。只要装上一个专门纠正语法错误的库就可以&#xff0c;还是毫秒钟就可揪出来的那种。这…

【shell】awk、sed、sort是什么?怎么用?

目录 一、AWK 干什么用的&#xff1f; 使用起来有什么条件&#xff1f; 怎么使用&#xff1f; 二、sed 功能&#xff1f; sed怎样读取数据&#xff1f; 怎样调用sed &#xff1f; 三、sort 功能是什么&#xff1f; 命令有哪些&#xff1f; 本文只讲解了一些简略的知…

“千年之恋”注册页面制作

“千年之恋”注册页面制作一、实验名称&#xff1a;二、实验日期&#xff1a;三、实验目的&#xff1a;四、实验内容&#xff1a;五、实验步骤&#xff1a;六、实验结果&#xff1a;七、源程序&#xff1a;八、心得体会&#xff1a;一、实验名称&#xff1a; “千年之恋”注册…

算法导论—SAT、NP、NPC、NP-Hard问题

算法导论—SAT、NP、NP-Hard、NPC问题SAT 问题基本定义问题复杂性P、NP、NP-Hard、NP-Complete&#xff08;NPC&#xff09;证明NP-Hard关系图NP问题的概念约化的定义NPC问题NP-Hard问题SAT 问题基本定义 SAT 问题 (Boolean satisfiability problem, 布尔可满足性问题,SAT): 给…

C++之完美转发、移动语义(forward、move函数)

完美转发1. 在函数模板中&#xff0c;可以将自己的参数“完美”地转发给其它函数。所谓完美&#xff0c;即不仅能准确地转发参数的值&#xff0c;还能保证被转发参数的左、右值属性不变。2. C11标准引入了右值引用和移动语义&#xff0c;所以&#xff0c;能否实现完美转发&…

「敏捷架构」敏捷架构:规模化敏捷开发的策略

与流行的看法相反&#xff0c;架构是敏捷软件开发工作的一个重要方面&#xff0c;就像传统的工作一样&#xff0c;并且是扩展敏捷方法以满足现代组织的现实需求的关键部分。但是&#xff0c;敏捷专家的架构方式与传统主义者的方式略有不同。本文讨论以下问题&#xff1a; 迈向敏…

Acer传奇Go电脑开机自动安装软件卡死怎么重装系统?

Acer传奇Go电脑开机自动安装软件卡死怎么重装系统&#xff1f;一些用户在网络上下载安装了一些恶意软件之后&#xff0c;导致电脑中了病毒。每次开机联网之后&#xff0c;有很多的软件就会自动开始下载&#xff0c;占满你的桌面&#xff0c;这个情况导致电脑直接卡死了&#xf…

前端知识点复盘

组件和jsx <body><div id"root"></div><script type"text/babel">const root ReactDOM.createRoot(document.getElementById("root"))class App extends React.Component {render() {return (<div> <h1>s…

MOTORTECH控制器维修燃气机点火模块MIC500

MOTORTECH发电机点火控制器模块维修注意事项: (1)由于主配电板经常发生振动,因此故障多发生在振动较强烈之处,所以要检查引起振动的原因并排除之,如躲开共振转速,增加防震垫片等。 (2)尘埃是造成接触不良的原因,对接线端子座及防尘罩等容易附着灰尘的场所要经常清扫。 1、看元…

2023级浙江大学MBA提面优秀资格最新经验分享

通过将近一年时间的奋斗&#xff0c;我的浙大MBA备考之路也算是告一段落了&#xff0c;在备考之初&#xff0c;我也在网络上看了很多“经验帖”&#xff0c;深知提前批面试对于浙大MBA录取来说这个有多重要&#xff0c;虽然我的笔试成绩还没有出来&#xff0c;但是在考完后估分…

HTTP请求返回304状态码以及研究nginx中的304

文章目录1. 引出问题2. 分析问题3. 解决问题4. 研究nginx中的3044.1 启动服务4.2 ETag说明4.3 响应头Cache-Control1. 引出问题 之前在调试接口时&#xff0c;代码总出现304问题&#xff0c;如下所示&#xff1a; 2. 分析问题 HTTP 304: Not Modified是什么意思&#xff1f; …

2022年新一代kaldi团队技术输出盘点

目录 1. 技术创新 1.1 Pruned RNN-T loss 1.2 RNN-T 的快速 GPU 解码 1.3 多码本量化索引的知识蒸馏 1.4 RNN-T 和 CTC 的低延时训练 1.5 Zipformer 1.6 Small tricks 2. 模型部署 2.1 Sherpa 2.1 Sherpa-ncnn 3. 更多的 recipe 和模型 参考资料 1. 技术创新 1.1 …