查找算法进阶:利用树的查找(二叉排序树、AVL树、多路查找树、B树)

本篇博客旨在学习查找算法。
最重要的四种查找算法:顺序查找、二分查找、哈希表查找、二叉排序树查找。
从二叉排序树可见,使用树这一结构,可以实现动态查找的高效率。

1 二叉排序树

二叉搜索树,顾名思义是一个二叉树,那么就有二叉树的优势:查找迅速、插入和删除不用移动元素。
现在我们需要对他做中序遍历时,得到有序的序列

1.1 性质

1、若他的左子树不空,则左子树所有结点的值小于根节点的值;
2、若他的右子树不空,则右子树所有结点的值大于根节点的值;
3、左右子树分别也都是二叉排序树;

1.2 操作

1、搜索:递归进行如下操作:如果查找关键字小于当前结点值,则在左子树继续查找;如果查找关键字大于当前结点值,则在右子树继续查找。递归终止条件:如果查找关键字等于当前结点值,则查找成功;或如果查找关键字不等于当前结点值且已经到了叶子结点,则查找失败。当然,如果没有根结点也是查找失败的情况。
2、插入:插入操作应该街上前面查找失败进行,此时创建一个结点。如果查找关键字小于当前结点值,则插入该结点作为左孩子;如果查找关键字大于当前结点值,则插入该结点作为右孩子。
3、删除:共有三种情况,对于待删除结点是叶子结点的情况,直接删去即可;对于待删除结点只有左子树或只有右子树的情况,直接将该子树放在原结点位置即可;但对于待删除结点有左子树并且有右子树的情况,就非常麻烦了,这时最简单的方法是找到删除结点的前驱和后继,也就是排序后最接近删除结点值的两个数字,可以选择将他们中的一个替换到删除结点的位置上。

1.3 优化

二叉排序树的形状是不固定的,因此会有全位于左子树或右子树的极端情况,同链表。因此我们更希望二叉搜索树是平衡的,即左右子树深度比较接近的。因此,下面的平衡二叉树就是对它的优化

2 平衡二叉树(AVL数)

平衡二叉树首先是一棵平二叉排序树,并且在此基础上,每一个结点的左子树和右子树的高度差至多为1.。总体来说,AVL树是将二叉排序树的不平衡消灭在最早时刻的树。

2.1 相关概念

1、平衡因子:二叉树结点左子树深度减去右子树深度的值。
2、平衡二叉树:所有结点的平衡因子绝对值都不大于1的树。
3、最小不平衡子树:距离插入结点最近,且平衡因子绝对值大于1的结点为根的子树。

2.2 实现原理

1、基本思想:插入一个结点时就检查是否破坏了树的平衡性,如果破坏了,则找出最小不平衡子树,进行左旋或右旋或交换位置,使其变得平衡。
2、右旋:平衡因子大于1时,将树顺时针旋转,更改根结点为中间的结点;
3、左旋:平衡因子小于-1时,将树逆时针旋转,更改根结点为中间的结点;

2.3 复杂度

1、查找操作的时间复杂度:O(logn)
2、插入和删除操作的时间复杂度:O(logn)

2.4 一点引申

关于STL中的关联容器,是基于红黑树来完成的,其效果和二叉排序树非常相似,两者也各自有各自的优势,因此map和set常用操作的时间复杂度也均约等于O(logn)

3 多路查找树

每一个结点孩子数可以多于2个,且每个节点可以存储多个元素来应对大数量元素,一般用于外存的查找,如硬盘。

3.1 2-3树

1、每个结点可以具有2个孩子(称为2结点)或3个孩子(称为2结点)或0个孩子;
2、2结点包含1个元素和2个孩子,3结点包含1个元素和3个孩子,他们可以没有孩子但不能孩子数不够;
3、有二叉排序树的性质:左子树均小于该元素,右子树均大于该元素,中间子树元素位于两者之间;

3.2 2-3-4树

是2-3树的扩展,一个4结点包含3个元素和4个孩子(也可能是没有);

4 平衡的多路查找树(B树)

B树即平衡的多路查找树,其比多路查找树增加了一个关键字项,使其知道该结点有多少个元素。
查找过程:顺时针查找结点+在结点查找关键字。

4.1 B树

1、每个非根的分支结点都有k-1个元素和k个孩子
2、所有叶子结点都在同一层级(每个子树深度相同);
3、最大孩子数目为m的,具有n个关键字的B树,最坏情况下涉及的结点数为以m/2为底(n+1)/2的对数。

4.2 B+树

为了避免中序遍历导致的多次访问同一个父节点,,出现在分支结点的元素会被当做他们在分支结点的中序后继者在此列出,且每个叶子结点都会保存一个指向后一叶子结点的指针。

猜你喜欢

转载自blog.csdn.net/weixin_42979679/article/details/102789587