持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天
二叉查找树
二叉查找树(又叫作二叉搜索树或二叉排序树)是一种数据结构,采用了图的树形结构。数据存储于二叉查找树的各个结点中
图示
01
结点中的数字便是存储的数据。此处以不存在相同数字为前提进行说明
02
二叉查找树有两个性质。第一个是每个结点的值均大于其左子树上任意一个结点的值。比如结点9大于其左子树上的3和8
03
同样,结点15也大于其左子树上任意一个结点的值
04
第二个是每个结点的值均小于其右子树上任意一个结点的值。比如结点15小于其右子树上的23、17和28
05
根据这两个性质可以得到以下结论。首先,二叉查找树的最小结点要从顶端开始,往其左下的末端寻找。此处最小值为3
06
反过来,二叉查找树的最大结点要从顶端开始,往其右下的末端寻找。此处最大值为28
07
试着往二叉查找树添加数据,如添加数字1
08
首先,从二叉查找树的顶端结点开始寻找添加数字的位置。将想要添加的1与该结点中的值进行比较,小于它则往左移,大于它则往右移
09
1<9,故将1左移
10
由于1<3,所以继续将1往左移,但前面已经没有结点了,所以把1作为新结点添加到左下方
11
1的添加操作完成
12
试着添加数字4
13
首先寻找添加数字的位置
14
4<9,左移
15
4>3,右移
16
由于4<8,所以需要将其往左移,但前面已经没有结点了,所以把4作为新结点添加到左下方
17
4的添加操作完成
18
接下来看看如何在二叉查找树中删除结点。比如删除结点28
19
若需要删除的结点没有子结点,直接删掉该结点即可
20
试着删除结点8
21
如果需要删除的结点只有一个子结点,那么先删掉目标结点
22
然后把子结点移到被删除结点的位置上即可
23
最后试着删除结点9
24
如果需要删除的结点有两个子结点,那么先删掉目标结点
25
然后在被删除结点的左子树中寻找最大结点
26
最后将最大结点移到被删除结点的位置上。这样一来,就能在满足二叉查找树性质的前提下删除结点了。如果需要移动的结点(此处为4)还有子结点,就递归执行前面的操作
27
下面来看如何在二叉树中查找结点,比如试着查找12
28
从二叉查找树的顶端结点开始往下查找。和添加数据时一样,把12和结点中的值进行比较,小于该结点的值则往左移,大于则往右移
提示:删除9的时候,我们将“左子树中的最大结点”移动到了删除结点的位置上,但是根据二叉查找树的性质可知,移动“右子树中的最小结点”也没有问题
29
12>4,右移
30
找到结点12
解说
我们可以把二叉查找树当作是二分查找算法思想的树形结构体现(二分查找的详细说明在3-2节)。因为它具有前面提到的那两个性质,所以在查找数据或寻找适合添加数据的位置时,只要将其和现有的数据比较大小,就可以根据比较结果得知该往哪边移动了。
比较的次数取决于树的高度。所以如果结点数为n,而且树的形状又较为均衡的话,比较大小和移动的次数最多就是log,n。因此,时间复杂度为O(logn)。但是,如果树的形状朝单侧纵向延伸,树就会变得很高,此时时间复杂度也就变成了O(n)。
补充说明
有很多以二叉查找树为基础扩展的数据结构,比如“平衡二叉查找树”。这种数据结构可以修正形状不均衡的树,让其始终保持均衡形态,以提高查找效率。
另外,虽然文中介绍的二叉查找树中一个结点最多有两个子结点,但我们可以把子结点数扩展为m(m为预先设定好的常数)。像这种子结点数可以自由设定,并且形状均衡的树便是B树。