引子
树形结构是一种非常重要的数据结构,很多同学学完树之后完全不知道树能够干什么?树都有哪些应用场景?
那么接下来我就和大家聊聊搜索树,这类树的应用十分广泛,比如数据库一般采用B-树或者B+树这种数据结构来进行高效地排序和检索。
在面试过程中,二叉搜索树、红黑树、AVL树以及B-树和B+树都是经常被面试官问到的!
一切还得从二叉搜索树(Binary Search Tree)说起。
二叉搜索树的基本性质:
-
若它的左子树不为空,则左子树上所有节点的值均小于根节点的值
-
若它的右子树不为空,则右子树上所有节点的值均大于根节点的值
-
它的左、右子树也分别为二叉搜索树
下图就是一棵二叉搜索树,可以看到这棵二叉搜索树满足上面所说的三种基本特性。
图解
那么这种数据结构有什么好处呢?我们可以先试着用它来查找数据,比如我们想要在这棵二叉搜索树中查找15。
Step1
首先从根节点的位置开始向下搜索,发现根节点处的数据为16,15<16,则可以推断15应该在当前节点的左子树中,那么我们去左子树中寻找。
Step2
此时来到左子树,又和左子树的根节点进行比较,发现15>10,则15应该在当前节点的右子树中,那么应该前往右子树中寻找。
Step3
此时来到右子树,当前根节点的数据为14,发现15>14,那么应该前往当前节点的右子树进行寻找。
Step4
又一次来到右子树,发现此时的根节点恰好为15,终于,经过上述的过程我们找到了想要的数据。
思考
简单回忆一下上述过程,我们不难发现,在寻找数据的过程中我们不需要将整个搜索树的每一个节点都遍历到,只需要在每一次寻找的时候和当前节点的值作比较:
-
若小于当前节点的值,则前往左子树寻找,右子树完全不用理会
-
若大于当前节点的值,则前往右子树寻找,左子树完全不用理会
-
若等于当前节点的值,则说明找到了数据
不难看出这其实是一个二分的过程,假设二叉搜索树共有N个节点,每个节点的左右子树的节点数目近似相等,那么可以推出二叉搜索树的查找效率为O(logN)。
看到这里可能很多同学会想,既然二叉搜索树的查找效率已经近似为O(logN)了,是一个非常好的效率了,为什么在实际应用中几乎没有二叉搜索树的影子?那就是因为二叉搜索树的性能不稳定,为什么不稳定呢?我们来看下面这种情况。
特例
如图也是一棵二叉搜索树,如果想要看看这棵二叉搜索树是否也有数据15,那么查找效率是多少呢?
Step1
首先从根节点的位置开始向下搜索,发现根节点处的数据为10,15>10,则可以推断15应该在当前节点的右子树中,那么我们去右子树中寻找。
Step2
此时来到右子树,发现根节点是11,15>11,那么再次前往当前节点的右子树中寻找。
Step3
来到新的树的根节点位置,发现当前节点13依然小于15,又一次前往当前节点的右子树。
Step4
最终,来到最新的一棵子树,发现当前根节点值为15,则找到了。
分析
分析上面的搜索过程,我们不难发现二叉搜索树在这种情况下(一般称为单枝树),查找效率降低了,假设二叉搜索树还是共有N个节点,但是其中一个子树形成了上面这种单枝树的情况,并且该单枝树的节点个数远大于另一个子树或者另一个子树节点数目可以忽略不计,那么在查找数据时,一旦我们要找寻的数据在单枝树上,则效率可能降为O(N)。所以正是这种效率上的不稳定性,让二叉搜索树一般只存在于教材当中作为讲解作用,很少用到实际场景中。
小结
- 一般情况下,二叉搜索树的查找效率是O(logN)
- 单枝树情况下,二叉搜索树的查找效率降为O(N)
后话
对于搜索树,我们一般用来进行搜索作用,所以只介绍二叉搜索树的查找过程,插入和删除过程与之类似,感兴趣的同学可以自己动手推一推哈!下期给大家搞个AVL树看看!
鄙人才疏学浅,若有任何差错,还望各位海涵,不吝指教!
喜欢本文的少侠们,欢迎长按下图关注公众号雷子的编程江湖,修炼更多武林秘籍。
一键三连是中华民族的当代美德!