C++ BST(二叉搜索树)

BST, 是一种完备二叉树。 顾名思义, binary search + tree, 可以实现二分查找法, 十分的高效。 BST 又被称为sorted binary tree。 是树的树结构中一种重要的数据结构。 对于每一个节点, 满足这个节点的所有左子树的各个节点的data 均小于(或者等于, 等于其实不太重要, 可以放在右子树部分)这个节点的数据, 右子树的所有节点的数据均大于这个节点的数据。

BST与其他数据结构相比, 主要的优点是与BST相关的排序算法和搜索算法(例如in-order traversal) 非常的高效。 除此之外, 还有如下优点:

(1)当BST是平衡的时候, 插入节点和删除节点的操作很快。

(2)代码简单, 容易实现。

(3)树中的节点是dynamic in nature(可以快速更新BST树, 易于修改)。

 

对于我们需要存储常常需要modifiable 的数据, BST的有事非常明显。 对于这种modifiable 的数据, 我们常常需要执行如下的基本操作:

下面对这种数据, 我们分析一下采用不同的数据结构, 各大基本操作的时间复杂度。

(1) 选择Array 的数据结构实现对数据的存储:

删除操作:

对于插入操作, 当我们的数组满了的时候, 我们需要申请一个更大的数组(通常2倍与原数组), 然后将数据复制到新的数组中, 此时该插入操作的时间复杂度会高达O(n)。

 

(2) 使用链表(例如linked list of integers)的时候:

NOTE: 下图中, 我们的插入操作是插在链表头中(故而时间复杂度为O(1), 如果插在尾部, 需要O(n)了), 删除节点需要先搜索, 故而为O(n):

不难看出, 采用上述的数据结构, 搜索某个元素花费的时间很多, 基本上需要很多次比较。我们已经知道, 如果我们在数组中存放着的是已经排好序的元素, 当我们需要查找某一个元素的时候, 可以采用binary search, 从而可以快速的找到数据。

此时时间复杂度为O(logn).

 

 

然而, 尽管查找的时间复杂度下降了(对于sorted Array, 查找只需要比较logn 次。), 但是插入和删除的时间复杂度却没有得到改善:

 

 

如何避免呢。 答案是采用BST(注意, 为了避免最坏的情况发生, 需要保证我们的BST是平衡的), 将上述三种基本操作的平均时间复杂度降至O(logn)。

                

 

下面对BST做简单介绍:

首先BST(注意树的这种递归的数据结构)如下图:

 

Q:判读下图是否为BST

A:(1)需要对每个节点进行分析:

首先对于根节点15:

     该节点左子树的所有节点均小于15, 右子树的所有节点均大于15, 所以满足, good node。

对于节点10, 同样的判断方式, 也是一个good node:

同理对于data 为20 的节点, 同样判断, 也是一个good node.

最后剩下叶子节点。 没有子树了, 停止。

所以上述的二叉树是一个BST。

 

Q1: 下图是一个BST吗

A: 不是的。 因为16 在15的左子树的节点, 但是大于15, 所以这个数不是一个BST。

 

 

为什么BST能够加快搜索的速度呢。

首先这源于二分法。 我们已经对对我们的数据排好序。 对于所有空间为n(数据项个数), 通过比较二分, 缩小我们的搜索空间大小, 最终实现准确定位:

 

使用BST的数据结构的时候, 搜索的操作和(用数组实现的)二分法是相似的。

例如下面的BST数据结构:

例如, 我们需要查找元素12.。 那么我们从根节点开始, 与根节点的数据(15)相比较, 由于比15小, 我们和左子树的根节点比较(数据为10), 由于12> 10, 向右子树走, 最终找到数据项12 的位置。 不难看出每一次决策在那个子树的时候, 其实就是在二分法(对于平衡的BST)。

 

设想一下, 如果我们的BST不是平衡的, 那么搜索的时间复杂度就是O(n)了, 并没有得到改善:

 

 

对于插入操作, 我们的第一步就是搜索确定被插入数据应该插在那个位置, 以便我们得到的二叉树任然是一个BST。

例如下例, 将19 插入到BST中:

首先, 从跟节点开始, 由于19大于15, 所以我们go right, 到达20, 由于19 < 20, 所以go right, 到达17, 17 < 19, 而且17没有右孩子,

 

 所以我们插在17 的右边, 创建一个数据为19 的node, link 起来, 作为其右孩子:

不难看出, 插入操作的时间复杂度也为O(logn)。

对于删除某个数据的操作, 我们的第一步也是搜索。 然后对link 进行调整。 一般而言, 时间复杂度也是O(logn)。

但是需要指出的是, 插入和删除操作可能会使得我们的BST不再是平衡的了。 所以一般在插入和删除操作完成之后, 我们常常需要做一些操作, 以便恢复BST的平衡性。

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值