数据结构----各种查找算法介绍及总结

查找

查找表:用于查找的数据集合称为查找表。包含三个操作,第一个是查阅某个数据元素是否在查找表中;第二个是查阅某个数据元素的属性;第三个是对查找表进行操作,比如插入或删除某个元素。

静态查找表:如果一个查找表仅仅涉及到前两个操作,那么就叫做静态查找表。比如顺序查找、折半查找等等;

动态查找表:比如二叉排序树、二叉平衡树

关键字:数据元素中某个可以唯一标识该元素的数据项。

平均查找长度(ASL:Average Search Length)
A S L = ∑ i = 1 n p i ∗ c i ASL=\sum_{i=1}^n p_i*c_i ASL=i=1npici
其中n表示的是查找表中数据元素的个数, p i p_i pi表示的是查找第i个元素的概率。 c i c_i ci表示的是找到第i个元素需要比较的关键字次数, 即查找长度。

顺序查找

顺序查找的两种实现,比如在一个线性表(数组)中查找一个数字是否存在。一种实现是从数组的首端开始,逐一对数组后续的数字进行比对;另一种实现是设置一个“哨兵”(也就是我们要查找的关键字)为数组的第1位(也就是下标为0),然后从数组末端依次向前进行比对。

对于查找成功的情况计算ASL: p i = 1 / n p_i=1/n pi=1/n, c i = i c_i=i ci=i,因此

A S L = ∑ i = 1 n 1 / n ∗ i = ( n + 1 ) / 2 ASL=\sum_{i=1}^n 1/n*i = (n+1)/2 ASL=i=1n1/ni=(n+1)/2

对于查找失败的情况计算ASL:假设有m值可以使其查找失败, p i = 1 / m p_i=1/m pi=1/m, c i = n c_i=n ci=n,因此

A S L = ∑ i = 1 m ( 1 / m ) ∗ n = n ASL=\sum_{i=1}^m (1/m)*n = n ASL=i=1m(1/m)n=n

综上,顺序查找的时间复杂度为O(n).

折半查找

折半查找适用于有序的顺序表。

折半查找判定树:就是用二叉树来刻画出一个折半查找查找数据的过程。

对于折半查找,查找的比较次数就是从根结点到该结点所经历的结点数。结合之前我们所学习过的具有N个结点的完全二叉树的高度为 l o g 2 ( N + 1 ) log_2(N+1) log2(N+1)(向上取整)。

因此折半查找的时间复杂度是O(logn)。

分块查找

分块查找也叫索引顺序查找。

首先确定待查找值在哪个块(可以利用折半查找的思想),其次就是在确定的块中查找待查找值(比如顺序查找的方法)。

可以说是结合了折半查找和顺序查找的优点,但是会空间换时间。


平衡二叉树

平衡二叉树:(AVL树)是一种特殊的二叉排序树。特殊的地方在于左右子树的高度之差绝对值不超过1,而且左右子树又是一棵平衡二叉树。定义结点左子树与右子树的高度差为该结点的平衡因子,那么平衡二叉树结点的平衡因子的值只可能是-1,0,1。

以距离插入结点最近的,(插入结点之后可能会导致其他结点不平衡,因此这个距离插入结点指的就是此时这些不平衡的其他结点与插入结点的距离)平衡因子绝对值大于1的这个结点为根的子树叫做最小不平衡子树

学会构建平衡二叉树

含有n个结点平衡二叉树的最大深度是 O ( l o g 2 n ) O(log_2n) O(log2n),因此平衡二叉树的ASL就是 O ( l o g 2 n ) O(log_2n) O(log2n)

性质:假设以 N h N_h Nh表示深度为h的平衡树中含有的最少结点数,因此, N 0 = 0 , N 1 = 1 , N 2 = 2 N_0=0,N_1=1,N_2=2 N0=0N1=1N2=2,并且 N h = N h − 1 + N h − 2 + 1 N_h=N_{h-1}+N_{h-2}+1 Nh=Nh1+Nh2+1.


二叉排序树

性质:左子树的所有结点的值都比根结点的值小,右子树所有结点的值都比根结点大;并且其左右子树也都是一棵二叉排序树。对二叉排序树进行中序遍历,得到的就是一个递增的有序序列。

二叉排序树的插入操作(借助其性质,并且可以使用递归的思想来实现)

二叉排序树的构建操作,借助二叉排序树的插入操作实现

二叉排序树的删除操作较为复杂,分为直接删除孩子结点;删除仅含有左子树或右子树的结点(直接讲被删除结点代替根节点即可);删除既含有左子树又含有右子树的结点(先找到被删除这个结点的直接前驱结点和直接后继结点,直接前驱结点也就是该结点左子树中最大的结点,直接后继结点也就是该右子树中最小的结点,然后随机用这两个结点来代替被删除的结点)。

B树和B+树(多路查找树)

2-3树是一种多路查找树,2和3的意思就是2-3树中包含有两种结点。

B树是一种平衡的多路查找树,2-3树和2-3-4树都是B树的一个特例,把树中结点最大的孩子数目称为B树的阶,记作m。一棵m阶B树或为空树,或为满足如下特性的m叉树:

树中每个结点最多有m棵子树,也就是最多含有m-1个关键字。如果根结点不是终端结点,那么至少有两棵子树;除根结点以外的所有非叶结点至少含有m/2(向上取整)棵子树。所有叶子结点出现在同一层次。

B树的构建、插入、删除操作。

散列表(Hash表)

之前我们所掌握的查找方法,无论是线性结构查找表还是树形结构查找表,都是用待查找的关键字来和表中的数据进行比对。

散列表:根据给定的关键字计算出关键字在表中的地址的数据结构。也就是说,散列表建立起了关键字和存储地址之间的一种直接映射关系。这个映射关系是通过一个散列函数得到的,就是把查找表中的关键字映射成关键字对应的地址的函数。记作Hash(key) = Addr.

散列函数可能会把两个或两个以上不同的关键字映射到同一个地址上,这种情况叫做冲突,这些发生碰撞的不同关键字叫做同义词

常用的Hash函数的构造方法

1.直接定址法:直接取关键字的某个线性函数值作为散列地址,散列函数表示为Hash(key) = a*key+b,其中a和b就是一个常数。简单,且不会产生冲突

2.除留余数法:假设散列表的表长为m,取一个不大于m但是最接近或等于m的质数p,然后借助公式将关键字转换为散列地址,散列函数表示为Hash(key)=key%p.其关键是选好p,使得每个关键字通过函数转换之后可以等概率的映射到散列空间上的任一地址,从而尽可能的减少冲突的可能性。

3.数字分析法:假设关键字是r进制数,而r个数码在各位上出现的概率不一定相同,可能在某些位上分布均匀,每种数码出现的机会均等,但是在某些位上分布不均匀,只有某几种数码经常出现,那么应该选取数码分布较为均匀的若干位作为散列地址,这种方法适用于已知的关键字集合。比如对于一个公司员工的手机号码,一般的前三位或者前七位会存在很多相同的地方,也就是十进制数字在手机号码上的前七位分布不均匀,因此我们可以选取每个人的手机号码的后四位作为散列地址。

4.平方取中法:也就是取关键字的平方值的中间几位作为散列地址,取多少位看实际情况。这种方法得到的散列地址与关键字的每一位都有关系,因此其散列地址分布较为均匀。

5.折叠法:将关键字分割成位数相同的几部分,取这几部分的叠加和作为散列地址。比如关键字是1234567890,散列表表长是3,因此就可以将其分解为123|456|789|0,叠加求和123+456+789+0=1368,取后三位368作为散列地址。

常用的hash函数的冲突处理办法:

1.开放地址法:就是将产生冲突的hash地址作为自变量,通过某种冲突解决函数得到一个新的空闲的hash地址。①线性探测法:也就是说,当冲突发生时,顺序查看表中的下一个单元,直到找到一个空闲单元。其缺点就是会造成大量元素在相邻的散列地址上聚集,这样会降低查找效率。举个例子,假设现在我们的散列函数是H(key)=key%8,有一个查找表的长度是9,现在对于关键字9而言,余数是1.因此存放到表中下标为1的位置,对于关键字11而言,存放在表中下标为3的位置,对于关键字19而言,本应该也是存放在表中下标为3的位置,但是因为此时下标为3的位置已经有数据了,因此向后找一个单元,发现下标为4的单元没有数据,因此19存放在下标为4的位置。现在我们回过头来分析查找19这个关键字的查找效率,按照之前的逻辑来说我们在表中下标为3的位置就应该找到,然而并不是这样,实际是在4的位置找到的,以此类推,如果有大量的余数为3的数字的话,那么都需要向后顺延,从而导致查找的时候效率大大降低。②平方探测法:假设发生冲突的地址为d,平方探测法得到的新的地址序列就是 d + 1 2 d+1^2 d+12, d − 1 2 d-1^2 d12, d + 2 2 d+2^2 d+22, d − 2 2 d-2^2 d22…平方探测法是一种比较好的解决冲突的一种方法,可以避免堆积问题,但是不能探测到散列表中的所有单元,但至少可以探测到一半单元。③再散列法:又叫做双散列法,需要使用两个散列函数,当通过第一个散列函数得到的地址发生冲突之后,利用第二个散列函数计算该关键字的地址增量。H=(Hash1(key)+Hash2(key)*i)%m,其中m指的是散列表的表长,i指的是冲突次数,初始值为0.④伪随机序列法:地址发生冲突时,地址增量为伪随机数序列。

2.拉链法:对于不同的关键字可能会通过散列函数映射到同一地址,为了避免非同义词发生冲突,可以把所有的同义词存储到一个线性链表当中,这个线性链表是由其散列地址唯一标识。拉链法适用于经常插入和删除的情况。

3.散列表的查找过程,类似于构造散列表,给定一个关键字key,先根据散列函数来计算出其散列地址,然后检查散列地址位置有没有关键字,如果没有就表明关键字不存在,如果有,就检查该记录是否等于关键字,如果等于关键字,查找成功,如果不等于,那么就按照给定的冲突处理办法来计算下一个散列地址,然后再执行之前的过程。

4.散列表的查找性能与装填因子有关。

装填因子 α \alpha α表示的是一个表的填满程度。计算方法等于 表中记录数m/散列表长度n。

散列表的平均查找长度依赖于散列表的装填因子 α \alpha α,并不直接依赖于n或m。 α \alpha α越大则表示装填的记录越满,发生冲突的可能性也就越大,反之发生冲突的可能性越小。

KMP算法

具体见有道云笔记或CSDN

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值