第7章小结

第七章小结 查找

根据这一章的题目,显而易见,这一张讲的是查找。虽然在之前的学习中,我们已经解除了不少的查找功能,但事实上,查找是一个可复杂可简单的过程。我们之前接触的查找大多数都比较的简单,而在学习完这一章后,我们会发现,事实上查找有很多种办法,也会发现,不同的情况,不同的存储结构都需要不同的查找方法。

以下为一些查找的概念和术语:

①关键字:数据元素(记录)中某个数据项的值,用它可以表示一个数据元素。

②动态查找表/静态查找表:若在查找的过程中进行修改操作(插入或删除),则相应的表为动态查找表,否则为静态查找表。

③平均查找长度:为确定记录在查找表中的位置,需和给定值进行比较的关键字个数的期望值称为查找算法在查找成功时的平均查找长度。公式如下:ASL=∑PiCi (i=1,2,3,…,n),可以简单以数学上的期望来这么理解。其中:Pi 为查找表中第i个数据元素的概率,Ci为找到第i个数据元素时已经比较过的次数。

下图为本章的主要结构:

线性表查找:

顺序查找:

从表的一端开始查找,依次将记录的关键字与给定的值进行比较,若有相等的则为成功,否则失败。这个是比较简单的。本章中引进了“哨兵”概念。可以免去查找过程中每一步都需要检测整个表是否查找完毕。

折半查找:搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

树表的查找:

二叉排序树:

性质:

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

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

(3)左、右子树也分别为二叉排序树;

二叉树的查找和插入都比较的简单,采用递归的方法就可以实现了。比较难搞定的是删除的操作,由于有不同的情况,所以也要应不不同的对付措施。在二叉排序树删去一个结点,分三种情况讨论:

若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则可以直接删除此子结点。

若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树(当*p是左子树)或右子树(当*p是右子树)即可,作此修改也不破坏二叉排序树的特性。

若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整,可以有两种做法:

其一是令*p的左子树为*f的左/右(依*p是*f的左子树还是右子树而定)子树,*s为*p左子树的最右下的结点,而*p的右子树为*s的右子树;

其二是令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继)-即让*f的左子树(如果有的话)成为*p左子树的最左下结点(如果有的话),再让*f成为*p的左右结点的父结点。

每个结点的C(i)为该结点的层次数。最坏情况下,当先后插入的关键字有序时,构成的二叉排序树蜕变为单支树,树的深度为其平均查找长度(n+1)/2(和顺序查找相同),最好的情况是二叉排序树的形态和折半查找的判定树相同,其平均查找长度和log 2 (n)成正比。

因此为了避免这种情况,引出了平衡二叉树的概念。

平衡二叉树:

它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

然而当数据量很大的时候,二叉树满足不了要求,这时候又提出了B树。

B树/B+树:

具体结构如下图:

其中B+树的理解,这一篇博客以图文的形式很好地诠释了。https://blog.csdn.net/qq_26222859/article/details/80631121

最后还有散列表:

在进行查找时,在记录的存储位置与它的关键字之间建立一个确定的对应关系h,以线性表中每个元素的关键字K为自变量,通过函数h(K)计算出该元素的存储位置,我们将h函数称为散列函数或哈希函数。这种查找方法称为散列查找。

散列函数:

构造散列函数的目标是使散列地址尽可能均匀分布在散列空间上,同时使计算尽可能简单,以节省计算时间。

①直接定址法

以关键字K本身或关键字加上某个数值常量C作为散列地址的方法,对应的散列函数:

h(K)=K+C (C为常数)

②除留余数法

以关键字K除以散列长度m所得余数作为散列地址的方法,对应的散列函数:

h(K)=K%m

③数字分析法

当关键码的位数很多时,可以通过对关键码的各位进行分析,丢掉分布不均的位,留下分布均与的位作为散列值。

④平方取中法

取关键字平方的中间几位作为散列地址的方法,由平方取中法得到的散列地址同关键字的每一位都有关,使得散列地址有较好分散性。

⑤折叠法:

首先将关键字分割成位数相同的几段(最后一段位数可少一些),然后将它们的叠加和(舍去最高位进位)作为散列地址的方法。

但是由于我们使用这些规则(函数)来获得相关下标的信息,难免就会有重复的时候。此时就会产生冲突。由此也有相应的措施来解决冲突的问题。

①开放定址法

思路:从发生冲突的那个单元开始,按照一定次序,从散列表中查找出一个空闲的存储单元,把发生冲突的待插入元素存入到该单元的一类处理冲突的方法:

1.线性探查法

是用开放定址法处理冲突的一种最简单的探查方法。

从发生冲突的d单元起,依次探查下一个单元,直到碰到一个空闲单元或探查完所有单元为止探查时,当达到下标为m-1的表尾单元时,下一个探查的单元是下标为0的表首单元。

探查序列为d,d+1,d+2……,表示为(d+i)%m (0≤i≤m-1)。

2.平方探查法

探查序列为d,d+1,d+2……,表示为(d+i2)%m(0≤i≤m/2)。

②链表地址法

链表地址法为散列表的每个表象建立一个单链表,用于链接同义词表,为此需要给每个表项增加一个指针域。

由于这一章的内容实在是太多了,还有很多的细节这里没有注意到。由于实践题最后一个测试点还没有顺利通过,所以这里也没办法进行讲述了。不过总体的思路也有了大概了,可能还是一些细节的问题没有找到。交了就回去看看了。

马上就要进入期末的复习阶段了。最近也有点忙。但是接下来的目标就是:

好好整理本学期学习过的内容,做一个比较完整的总结。准备迎接期末了。

原文地址:https://www.cnblogs.com/ilikezero/p/10962917.html

时间: 2024-10-29 07:32:17

第7章小结的相关文章

C++ 编程第二章小结

switch()用法的注意事项 1:switch语句中的表达式只能是整形数据,字符型数据和枚举型数据,case后面的产量表达式的类型必须与switch括号后面的类型相匹配 2:各个case(包括default)的出现次序可以任意,每个case在带有break的前提下,case的次序不影响执行结果 循环设计 循环设计的几种分类方法这里介绍几种 1:字符图形类 2:素数判断类 3:逻辑判断类 4:级数逼近类 a:对于图形类的基本循环格式一般是 for(int i = 1; i < 10 ;i ++)

17._11本章小结及任务实施

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Text.RegularExpressions; using System.Collections; namespace _17._11本章小结及任务实施 { class Program { static void Main(string[]

18._7章小结及任务实施

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _18._7章小结及任务实施 { class QQState { string[] qqState = {"在线","离线","Q我","隐身","忙碌" }

shell学习小总结----本章小结

本章小结 变量在正是一点的程序里是必备项目.shell的变量会保留字符串值,而大量的运算符可以在${var...}里使用,让你控制变量的结果. shell提供了许多的特殊变量(例如#?与$!),用来访问特殊信息,例如,命令退出状态.shell也有许多预定义的特殊变量,例如PS1----用来设置主要提示符.位置参数与$*和[email protected]这类的特殊变量,则用来在脚本(或函数)被引用是,让用户可以访问被使用的参数.env,export以及readonly则用来控制环境. $((..

第二章小结

第二章小结 早听说数据结构要比程序设计要难,我早早就做好了心理准备,可是现实好像比我想象的还要难一些.这个星期基本结束了第二章关于线性表的学习.对于顺序表,上学期接触的比较多学起来还算比较顺利.链表就有一点困难了.书上没有完整的代码段,只是一些算法,不得不说一开始我真的有点蒙圈的感觉.但后面经过了预习以及上网查找资料就开始慢慢接受了单链表. 和顺序表不同,单链表是存储在连续或者不连续的空间里面的.每一个数据都必须跟着一个地址,指向下一个数据.虽然可能空间利用率比不上顺序表,但在插入删除操作时就显

第三章小结--栈与队列

第三章小结 第三章我们主要学习了栈和队列.经过第一次的写博客,与课后的学习与借鉴.我看到很多其他的同学在整理知识的时候采用了画大纲图,架构图的方法.不得不说,那样子确实比纯粹的文字更加简单明了.于是我决定也学习和效仿一下. 以下便是图解: 通过大图来看,很明显,和前面学习的顺序表,链表栈和队列的操作有同工异曲之妙.实际上围绕着栈和队列的也是分为两大分支,顺序表和链表.操作也是从初始化,插入,删除,查找几个操作入手. 当然,也有不同的地方,栈是典型的先进而后出,队列则是先进先出,其插入和删除的操作

Unity 游戏框架搭建 2019 (九~十二) 第一章小结&amp;第二章简介&amp;第八个示例

第一章小结 为了强化教程的重点,会在合适的时候进行总结与快速复习. 第二章 简介 在第一章我们做了知识库的准备,从而让我们更高效地收集示例. 在第二章,我们就用准备好的导出工具试着收集几个示例,这些示例中有的是我们后续库的基础工具,也有的是在项目中非常实用的小工具,还有一些示例是实践了在框架搭建方向上非常重要的 C# 语法知识. 第二章大纲如下. 第八个示例(一) 在之前,我们完成了一个导出的功能.但是在完成这个功能的过程中,我们也遇到了一些问题.我们回忆一下,在<MenuItem 复用>的这

汇编语言第三章小结

第三章 内存访问 字数据在内存中的存储 1.      内存以字节为单位,划分为若干个单元 2.      字数据的存-取原则:高-高  低-低(小端法) 即: ① 字数据的低位字节存放在低地址内存单元 字数据的高位字节存放在高地址内存单元 ② 取低地址内存单元地址作为字数据地址 例1: 字数据124EH的地址是( 1 ) 字数据3020H存入内存后地址为4,则4存放( 30H ),3存放( 20H ) 例2: 从地址单元1取出一个 (1)     字节数据为:  4EH (2)     字数据

DS第三章小结

一.你对本章内容的小结 本章主要讲了两种特殊的线性表,栈和队列.栈是仅在表尾进行插入或删除操作且后进先出(LIFO)的线性表,而队列则是在表的一端插入,另一端删除元素且先进先出(FIFO)的线性表.同时,课本的案例引入告诉我们,栈可以解决数值的转换,括号匹配的检验问题:而队列因其结构的吻合可以用了舞伴问题. 下面是本章的思维导图.对我来说,第三章比第二章更抽象,晦涩,难懂,仍然需要通过练习来对机械地吸收的知识加以运用. 二.完成作业实践时的心得体会 首先还是要多看课本,把基本的入栈,出栈,入队,