大话数据结构笔记-查找
查找就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录)。
查找概论
查找表是由同一类型的数据元素(或记录)构成的集合。
关键字(key)是数据元素中某个数据项的值。
若此关键字可以唯一的表示一个记录,则称此关键字为 主关键字(Primary Key)。
对于那些可以识别多个数据元素(或记录)的关键字,我们称为 次关键字(Secondary Key)。
- 静态查找表(Static Search Table):只作查找操作的查找表。
- 查询某个“特定的”数据元素是否在查找表中。
- 检索某个“特定的”数据元素和各种属性。
- 动态查找表(Dynamic Search Table):在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。
- 查找时插入数据元素。
- 查找是删除数据元素。
顺序表查找
针对线性表进行查找的操作是静态查找表。
顺序查找(Sequential Search)又叫线性查找,是最基本的查找技术,他的查找过程是:从表中第一个(或最后一个)记录开始,逐个进行记录的关键字和给定值比较,若某个记录的关键字和给定值相等,则查找成功,找到所查的记录;如果直到最后一个(或第一个)记录,其关键字和给定值比较都不等时,则表中没有所查的记录,查找不成功。
有序表查找
半折查找
半折查找(Binary Search)技术又称为 二分查找。
在有序表中,取中间记录作为对象,于给定值比较,根据结果在子分类中在取中间记录比较,直到找到记录。
插值查找
插值查找(Interpolation Search):是根据要查找的关键字Key于查找表中最大最小记录的关键字比较后的查找方法,其核心就在于插值的计算公式(key-a[low])/(a[high]-a[low])
斐波那契查找
恩,挺复杂
线性索引查找
索引就是把一个关键字与对应的记录相关链的过程。
线性索引就是将索引向集合组织为线性结构,也称为索引表。
稠密索引
稠密索引是指在线性索引中,将数据集中的每个记录对应一个索引项。
对于稠密索引这个索引表来说,索引项一定是按照关键码有序的排列。
分块索引
分块有序,是把数据集的记录分成了若干块,并且这些块需要满足两个条件:
- 块内无序,即每一块内的记录不要求有序。(最好有序)
- 块间有序,即第一块的关键字均要大于第二块。
分块索引的索引项结构分三个项目:
- 最大关键码,他存储每一块的最大关键字,好处是可以使得在它之后的下一块中的最小关键字也能比这一块的关键字大。
- 存储了块的记录个数,以便于循环是使用。
- 用于指向块首数据元素的指针,便于开始对这一块中的记录进行遍历。
分块索引表中查找分为两步:
- 在分块索引表中查找要查找关键字所在的块。
- 根据块首的指针找到相应的块,并在块中顺序查找关键码。(因为块内无序)
倒排索引
说白了就是根据属性值查找记录。
结构:
- 次关键码
- 记录号表
记录号表存储具有相同次关键字的所有记录的记录号(可以是指向记录的指针或者该记录的主键)。
这样的索引方法就是倒排索引(inverted index)
因为需要根据属性去找记录,所以叫倒排。
二叉排序树
二叉排序树(Binary Sort Tree) 又称二叉查找树,它或者是一颗空树,或者是具有下列性质的树。
- 若它的左子树不空,则左子树上所有结点的值均小于它的跟结构的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的跟结构的值;
- 它的左右子树也分别为二叉树。
二叉树是以链接的方式存储,保持了链接存储结构在执行插入或删除操作是不需要移动元素的优点。
平衡二叉树(AVL树)
平衡二叉树(Self-Balancing Search Tree 或 Height-Balanced Binary Search Tree),是一种二叉排序树,其中每个节点的左子树和右子树的高度差最多等于1.
是一种高度平衡的二叉排序树。
将二叉树上结点的左子树深度减去右子树深度的值称为平衡因子BF(Balance Factor)。
距离插入结点最近的,且平衡因子的绝对值大于1的结点为跟的子树,我们称为最小不平衡子树。
多路查找树(B树)
多路查找树(Muitl-way search tree),其每个结点的孩子数可以多于两个,且每个结点处可以存储多个元素。
由于 它是查找树,所有元素之间存在某种特定的排序关系。
2-3树
2-3树:
- 其中的每一个结点都具有两个孩子(我们称它为2结点)或三个孩子(我们称为3结点)。
- 一个2结点包含一个元素和两个孩子(或没有孩子)。
- 一个3结点包含一大一小两个元素和三个孩子(或没有孩子)。
2-3-4树
就是2-3树的概念,包括了4结点的使用,一个4结点包含大中小三个元素和四个孩子(或没有孩子)。
B树
一种平衡的多路查找树。
结点最大的孩子数目称为B树的阶(order)。
B+树
B+树和B树的区别:
- 有n棵子树的结点中包含有n个关键字
- 所有的叶子结点包含全部关键字的信息,及指向含有这些关键字记录的指针,叶子结点本身依关键字的大小自小而大顺序链接;
- 所有分支结点可以看成索引,结点中仅含有其子树中的最大(或最小)关键字。
散列表查找(哈希表)
散列技术是在记录的储存位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)。查找时,根据这个确定的对应关系找到给定值key的映射f(key),若查找集合中存在这个记录,则必定在f(key)的位置上。
我们把这种对应关系f称为散列函数,又称为哈希(Hash)函数。
采用散列技术将记存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表(Hash table)。
散列技术最适合的求解问题是查找与给定值相等的记录。
散列函数的构造方法
散列函数的要求:
- 计算简单
- 散列地址均匀分布
选择散列函数的参考因素:
- 计算散列地址所需的时间
- 关键字长度
- 散列表的大小
- 关键字的分布情况
- 记录查找频率
直接定址法
取关键字的某个线性函数值为散列地址。
f(key) = a*key+b
- 简单均匀,也不会产生冲突。
- 需要预先知道关键字的分布情况。
- 适合查找表较小且不连续的情况。
数字分析法
适合关键字是位数较多的数字
抽取出关键字的一部分来计算散列函数。
适合关键字位数较大,且事先知道关键字的若干位分布均匀。
平方取中法
将关键字平方然后取中间的几位作为散列地址。
适合不知道关键字分布,而且位数不是很大的情况。
折叠法
将关键字从左至右分为位数相等的几段,然后叠加求和,再根据散列表的表长取后几位作为散列地址。
除留余数法
最常用的构造散列函数的方法。
f(key)=key mod p (p<=m)
mod是取模(求余数)的意思。
方法的关键在于取合理的p避免产生同义词。
根据之前的经验,若散列表表长为m,通常p为小于或等于表长(最好接近m)的最小质数或不包含小于20质因子的合数。
随机数法
选择一个随机数,取关键字的随机函数值为它的散列地址。
也就是:
f(key)=random(key)
关键字长度不等时,采用这个方法比较合适。
处理散列冲突的方法
开放定址法
开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将其记录存入。
我们把解决冲突的开放定址法称为 线性探测法。
本来都不是同义词却需要争夺一个地址的情况叫做堆积。
再散列函数法
就是当第一种散列函数存在冲突的时候换一种散列方式进行计算。
链地址法
把同义词存在单链表中,依次查找。
公共溢出区法
就是单独规定出一个溢出区域(溢出表)来记录冲突的记录。