数据结构-查找

数据结构-查找

查找基本概念
1.查找:在数据集合中寻找满足要求的的数据元素成为查找,查找有两种结果1.查找成功,找到目标元素;2.查找失败,遍历完集合仍未找到目标元素。
2.查找表:用于查找的数据集合叫做查找表,由同一类型的数据元素组成。对查找表的操作一般有四种1.查找某个元素是否在查找表中 2.访问目标元素 3.向查找表中插入元素 4.从查找表中删除元素。

查找的类别

顺序查找
顺序查找又叫线性查找,从线性表的一端顺序查找到另一端。顺序查找既可用于顺序表,也适用于链表。当被查找的线性表有序时,则不必一一遍历线性表中的元素,可以使用折半查找,减少时间复杂度。

折半查找(二分查找):当线性表是有序序列时(假设是增序),可以把目标元素与线性表中间元素比较,如果目标元素比中间元素小,则在前半段序列中寻找,因为后半段元素必定大于目标元素,目标元素比不可能在后半段,所以后半段元素不必遍历。反之亦然。因为每次比较都会排除一半元素,所以折半查找复杂度为O(logn)。(可以把折半查找看成是在一颗平衡二叉树上查找)。因为折半查找需要快速定位到中间元素,所以折半查找适合顺序存储结构,不适合链式存储结构,且要求序列有序。

分块查找:把查找序列分成若干块,块内序列可以无序,块间有序(例如升序,第一块中的最大元素小于第二块中的最小元素)。查找时先对所有块进行折半查找,找到目标块后在块内进行顺序查找。时间复杂度为O(logb+s/2)(其中b为块的数量,s为块内元素数量)理想的块内元素个数为n^(1/2)。(可以把分块查找看成是在B+树上查找)。

B树和B+树
B树又称多路平衡查找树。B树的节点中有多个关键字,B树中所有节点的孩子节点个数最大值叫做B树的阶,用m表示。一棵m阶B树要么是空树,要么满足以下条件:
1.树中每个节点最多有m棵子树,最多有m-1个关键字。
2.若根节点不是终端节点,则至少有两棵子树。
3.除根节点外所有非叶节点至少有(m/2向上取整)棵子树,至少含有(m/2向上取整)-1个关键字。
4.每个节点包括n(节点中关键字的个数),pi(指向子树的指针,该子树的节点均小于ki,大于k(i-1)),ki(节点中的关键字)。
5.所有叶节点都在同一层,且不携带任何信息(这些节点又叫外部节点)。
6.节点中的关键字是有序的(递增)

B树查找从根节点开始,遍历到目标节点后再在节点内查找。B树一般存储在磁盘上,当在B树中找到目标节点,操作系统会将节点信息读入内存,在内存中使用顺序查找或二分查找等找到目标元素。
B树插入首先定位到要插入的位置(插入位置一定在最底层的非叶节点中),插入后如果不满足B树则需要调整,一般是向上分裂(节点超出最大节点数,分出一个节点到父节点…根节点超出节点数向上分裂出新节点,树高度增加)。
B树删除时节点数小于最小节点数时需要借其他节点的关键字或者合并节点,直到符合B树要求。

B+树和B树类似,对于m阶B+树,与B树有以下不同:
B+树节点关键字和子树个数相同,每个关键字对应一棵子树,且该关键字等于子树中的关键字最大值。
B+树关键字的个数最多为m个。
B+树没有外部节点。
B+树信息都存储在叶节点中非叶节点不包含信息(只有对应子树的最大关键字和指向该子树的指针),B数中每个节点都存有信息。
B+树有两个指针,一个是指向根节点指针(和普通的树一样),一个指向关键字最小的节点(B+树所有叶节点是按关键字从小到达连接的)。有两种遍历方式:从根节点遍历(树遍历),从最小关键字节点遍历(链表遍历)。
因为B+树只有叶节点存有信息,查找时需要遍历到叶节点。B+树插入和删除和B树类似。

散列表
基本概念
散列函数:把关键字映射成对应地址的函数。散列函数可能会把多个元素映射到同一个地址,这种情况叫做冲突。发生冲突的关键字称为同义词。选择散列函数应尽量避免产生冲突。
散列表:根据关键字可直接访问的数据结构,散列函数就是把关键字映射到散列表中。散列表查找只需根据散列函数计算得到地址,时间复杂度为O(1)。

散列函数构造方法
直接定址法:直接取关键字的某个线性函数值为散列地址,散列函数为
H(key)=key*a+b
a ,b ,为常数。这种方法简单,适合关键字分布连续的情况。

除留余数法:假定散列表长为m,取一个不大于m的最大质数p(选质数减小产生冲突的概率)。散列函数为
H(key)=key%p
一般都是采用这种方法。

数字分析法:根据关键字分布比较均匀的若干位作为散列地址。适合已知的关键字集合。

平法取中法:取关键字平方值的中间几位作为散列地址。适用于关键字的每位取值都不够均匀或均小于散列地址所需的位数。

处理冲突的方法
开放定址法:把空闲地址向非同义词开发(同义词和非同义词都可存放在这个地址),公式:Hi = (H (key) +di)%m Hi为散列后的地址,H(key)为关键字, m为散列表长,di为增量序列。
开放定址法又细分三种

线性探测法:增量序列为0,1,2,3…m-1线性递增。特点 发生冲突时顺序查看下一个单元(当此时为最后一个单元时下一个查看的是散列表表首地址),但是这样会造成大量元素在相邻的散列地址上聚集起来,降低查找效率。(b被a占了地址,b占了旁边c的地址,c又会去占它旁边的地址)

平方探测法(二次探测法):增量序列为0^2 1^2 -1^2…(0,1,-1,4,-4…)。散列表长度m必须是一个可以表示为4k+3的质数。特点 不会造成堆积,但只能探测到散列表一半的单元。

再散列法: 再设计一个散列函数Hash2, 增量序列为i*Hash2,i为产生冲突的次数,最多经过m-1次探测就会回到原位置(i=0时的位置)。

伪随机序列法: 增量序列为伪随机数。

在开放定址法的情形下,被删除的地址不能直接在物理上删除,因为它的同义词还与该元素有关,可以设置标记是否被删除。不过这会造成看起来散列表是满的,但实际很多元素都已被删除,需要定期维护(可以直接用新的关键字散列后直接覆盖)。

拉链法:同义词用链表串起来。

散列表的查找效率取决于散列函数,处理冲突方法,装填因子
装填因子=表中的记录数n/表长m
散列表平均查找长度(ASL)依赖于装填因子,装填因子越大,发生冲突的概率越大。

你可能感兴趣的:(面试算法,c语言,算法,数据结构)