c语言折半查找法_数据与算法总结——基本非数值算法1(查找)

b9cced2348a39198d40ff4008c1459c3.png

3 基本非数值算法

3.1 查找

3.1.1 顺序查找和索引查找

查找表

查找表是由同一类型数据元素构成的集合。

按关键字查找:查询某数据元素是否存在;检索某数据元素的各种属性;在查找表中插入一个数据元素;从查找表中删除一个数据元素。

查找表的北星:静态查找表、动态查找表。

查找的性能分析:平均查找长度(在查找过程中,为确定目标在查找表中的位置,需要进行关键字比较次数的期望值)

,其中
分别为第i条记录的查找概率和查找长度。需要考虑每条记录的查找概率相等、每条记录的查找概率不等、查找不成功的情况。ASL越小,查找的性能越好。

顺序查找:对顺序表或者线性链表可以采用顺序查找;顺序查找又称线性查找,是从线性表的一端开始,依次把每个元素的关键字同给定值进行比较。

假设每个元素的查找概率相等,则平均查找长度为:

对于长度为N的线性表,平均来说顺序查找需要进行

次比较,更多的考虑:概率不相等;对于长度为N的线性表,查找失败需要N次比较;越界判断。

线性查找表一般不是按关键字有序排列的;如果线性查找表是从小到大有序排列的,那么当遇到关键字较给定值大的元素,即可认为查找失败;对于长度为N的有序表,查找失败需要

次比较。

折半查找:如果顺序表有序,我们可以采用高效率的折半查找。

折半查找可以用一个二叉树结构来描述,二叉树的深度是折半查找需要的比较次数。

不同线性表的查找效率比较:

索引查找

基本思想:将有n个结点的线性表划分为m个子表,分别存储各字表;另设一个有m个结点(索引项)的索引表,每个节点存子表第一个结点的地址以及相关信息。

线性表划分原则:具有某种性质

的结点归并到子表
中;m个子表的结点结合在一起,正好构成原线性表L的全部结点。

关键是确定索引函数。

3.1.2 二叉搜索树

二叉搜索树,每个结点都有一个关键字并且:任意结点关键字大于等于该结点左子树中所有结点含有的关键字;同时该结点的关键字小于等于右子树中所有结点含有的关键字。或者是空树。

二叉搜索树的遍历:中序遍历二叉搜索树:

17d6eed78b97317da31e0ffac8a3a8ae.png

中序遍历序列是一个有序序列,一棵二叉搜索树代表了一个经过排序的关键字序列,对应与一个关键字序列有多棵二叉搜索树,部分有序。

二叉搜索树上的算法运行时间由树的形状决定。

对于一棵含有N个关键字的BST,最好情况下,所有搜索都可以保证对数运行时间,最坏情况下,进行一次搜索需要N次比较,平均情况下搜索需要

次比较操作。

BST中的删除操作:比较复杂。分三种情况讨论:删除的为叶子结点、待删除结点的左子树为空,或者右子树为空;待删除结点的左右子树都不为空。

前两种比较简单,叶子直接删,只有一个子树的直接接过来就行了。

如果待删除结点的左右子树都不空,可以用中序前驱或者中序后继代替。

BST中的旋转:旋转是对于树的一种基本转换操作,旋转使一棵树中,结点和结点的一个子孙互换角色,但仍然保持结点关键字之间的次序。右旋转涉及到结点及其左孩子,左旋转涉及到结点及其右孩子。

右旋转:

7504a1e7269a8c12c33384f400996297.png

21449861630b1254a40ca866d11aec62.png

左旋转:

af8ddee58ce2542a05bcab1ecf19852f.png

de88fdc686ab7656d245d992d2dc76e1.png

BST的基本搜索,插入和排序操作都易于实现,但是平衡性可能变得很差,并引起性能急剧降低。

高度平衡的二叉搜索树:AVL树。实用的平衡二叉搜索树:红黑树。多路平衡的动态查找结构:B-树。

3.1.3 散列

散列函数是将关键字集合映射到某个地址集合上的映射。

散列技术关心记录存放位置和关键字之间的对应关系。

散列表(Hash)是将一组关键字映像到一个有限的、地址连续的区间上,并以关键字在地址集中的“像“作为相应记录在表中的存储位置。

经常出现两个或多个关键字对应同一表地址的情况,这就是“冲突”现象,于是就有了冲突调节。

散列是一种合理调整的存储量和查找时间的方法,散列技术主要有两个部分:散列函数和冲突处理。

构造原则:简单、定义域和值域、随机

乘法散列函数,只有当关键字在一定平均分布时,这种散列函数才是高效的。

模散列函数:用整型关键字k对M求模,其中,M不大于表长,M为素数,或者至少没有小于20的质因子。

或者乘法与取模两种算法相结合,将关键字乘以0到1之间的一个常数然后做模M运算:

,一个常用的
是0.618033(黄金分割比)

数学分析法:仅适用于事先明确知道表中所有关键码每一位数值的分布情况,完全依赖于关键码的集合。有n个d位数,每一位可能有r种不同的符号。这r种不同的符号在各位上出现的频率不一定相同,可根据散列表的大小,选取其中各种符号分布均匀的若干位作为散列地址。

平方取中法:先计算构成关键码的标示符的内码的平方,然后按照散列表的大小取中间的若干位作为散列地址。

折叠法:把关键码自左向右分成位数相等的几部分,每部分的位数应与散列表地址位数相同,只有最后一部分的位数可以短一些。把这些部分的数据折叠起来,就可以得到具有该关键码的记录的散列地址。

两种:移位法(把各部分的最后一位对齐相加)和分界法(各部分不折断,沿各部分的分界来回折叠,然后对齐相加,将相加的结果当作散列地址)。

冲突处理:

链地址法:对应每个散列地址建立一个链表。

开放定址法:决定给定的表位置上是否存在一个与搜索关键词不同的元素的检查成为探测,当冲突发生时,即把元素插入的位置已经被另一个不同的元素占据,我们查找表中的下一个位置,称为线性探测(最简单的开放定址法)。

线性探测列的建立:如果表位置上为空,插入元素。如果表位置上的元素与搜索关键字不匹配,我们继续探测表的后续位置,如果搜索到表尾要回到表头继续。

留个坑

Hash表的查找

查找过程与建表过程一致,假设采用开放定址法处理冲突,则查找过程为:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值