查找的基本概念
查找表
由类型相同的数据元素(或记录)所组成的集合。查找表中每个记录由若干数据项组成。若表中总有一个或几个属性能够唯一地确定一条记录,则称这个属性(或属性组合)为关键字。
查找
在含有若干记录的查找表中找出关键字值与给定值相同的记录。若查找成功,返回所找到的记录的信息或返回所找到的记录在表中的位置;否则查找失败,返回空记录或空指针。
查找表的基本操作
1.查找某个特定的数据元素是否在查找表中。
2.检索某个特定的数据元素的各种属性。
3.在查找表中插入一个数据元素。
4.从查找表中删除某个元素。
查找表的分类
一:按查找表的元素是否发生变化分类
1.动态查找表:在查找的同时对表做更新操作
2.静态查找表:在查找过程中仅对表内数据进行查询检索和读取操作
二:按查找过程是否使用外存分类
1.内查找:整个查找过程都在内存进行
2.外查找:整个查找过程需要访问内存
顺序查找
从表的一端开始,依次将表中元素关键字和给定的key值比较,若某个记录关键字值与给定值相等,查找成功;反之查找失败。
二分查找
也成折半查找,略。
分块查找
又称索引顺序查找,为顺序查找与二分查找的综合运用,略。
二叉排序树
也称作二叉查找树,一般定义为或者是空树,或者是满足以下条件的二叉树:
1.若它的左子树不空,则左子树上所有记录的关键字值均小于根记录关键字值
2.若它的右子树不空,则右子树上所有记录的关键字值均大于根记录关键字值
3.它的左右子树本身也是二叉排序树
平衡二叉树
二叉树中每个结点的左右子树深度之差的绝对值不大于1的二叉树称为平衡二叉树(AVL树),在二叉排序树的结点中增加一个平衡因子域,每个结点的平衡因子是该结点的左子树的高度与右子树的高度之差。
散列表
让记录在表中位置和其关键字之间存在一种确定的关系
对于动态查找表而言表长不确定,在设计查找表时,只知道关键字所属范围,而不知道确切的关键字。因此需要在关键字集和地址集之间建立一个映射关系,以H(key)作为关键字为key的记录在表中的位置,通常称这个函数H(key)为散列函数或哈希函数,它不一定是数学函数。
在一般情况下,散列函数是一个压缩映象。因此很容易产生冲突,即key1 != key2,而H(key1) == H(key2)。通常把这种关键字不同而散列地址相同的关键词称作同义词,由同义词引起的冲突称为同义词冲突。
散列函数的构造方法
直接定址法:散列函数为关键字的线性函数H(key)=a * key + b 直接定址所得地址集合与关键字集和的大小相同。对于不同的关键字不会发生冲突。
数字分析法:假设关键字集合中的每个关键字都是由s位数字组成(k1,k2,…,kn),分析关键字集并从中提取分布均匀的若干位或它们的组合作为地址
平方取中法:若关键字的每一位都有某些数字重复出现频度很高的现象,则先求关键字的平方,扩大差别,一个数平方后的中间几位受到整个关键字中各个数位的影响,可增加随机性。
折叠法:若关键字的位数特别多,则可将其分割成几部分,然后取他们的叠加和作为散列地址。叠加后舍弃进位。
随机数法:通过随机函数对每个关键字产生一个随机数作为散列地址:
H(key) = random(key),一般用于关键字长度不等的情况下。
除留余数法:用关键字key除以一个小于或等于散列表长度m的整数p后得到的余数作为散列地址:H(key) = key%p(p<=m)
处理冲突的方法
开放地址法
开放地址就是散列表中尚未被占用的地址。开放地址法就是为产生冲突的关键字所对应的记录求得一个地址序列:H1,H2,…,Hs
其中H0 = H(key),Hi = (H(key) + di)% m,按此序列不断探测,直到找到空间地址位置。增量di有三种取法:
1.线性探测再散列:
di = i
2.二次探测再散列,也称平方探测再散列:
di = ±i^2
3.随机探测再散列:
di是一组为随机数列
链地址法
又称拉链法和外部链接法,将所有散列地址相同的记录都连接在同一链表中。因此在这种方法中,散列表的每个单元存放的不再是对象,而是相应同义词单链表的头指针。
建立公共溢出区
另外创建一个线性表,将所有与散列表中关键字发生冲突的记录都加入到该表中,这样的线性表就称为公共溢出区。