二叉搜索树简介
二叉搜索树简介¶
二叉搜索树是一种二叉树的树形数据结构,其定义如下:
-
空树是二叉搜索树。
-
若二叉搜索树的左子树不为空,则其左子树上所有点的附加权值均小于其根节点的值。
-
若二叉搜索树的右子树不为空,则其右子树上所有点的附加权值均大于其根节点的值。
-
二叉搜索树的左右子树均为二叉搜索树。
二叉搜索树上的基本操作所花费的时间与这棵树的高度成正比。对于一个有 n 个结点的二叉搜索树中,这些操作的最优时间复杂度为 O(\log n),最坏为 O(n)。随机构造这样一棵二叉搜索树的期望高度为 O(\log n)。
基本操作¶
在接下来的代码块中,我们约定 n 为结点个数,h 为高度,val[x] 为结点 x 处存的数值,cnt[x] 为结点 x 存的值所出现的次数,lc[x] 和 rc[x] 分别为结点 x 的左子结点和右子结点,siz[x] 为结点的子树大小。
遍历二叉搜索树¶
由二叉搜索树的递归定义可得,二叉搜索树的中序遍历权值的序列为非降的序列。时间复杂度为 O(n)。
遍历一棵二叉搜索树的代码如下:
1 2 3 4 5 6 7 | |
查找最小/最大值¶
由二叉搜索树的性质可得,二叉搜索树上的最小值为二叉搜索树左链的顶点,最大值为二叉搜索树右链的顶点。时间复杂度为 O(h)。
findmin 和 findmax 函数分别返回最小值和最大值所对应的结点编号 o,用 val[o] 可以获得相应的最小/最大值。
1 2 3 4 5 6 7 8 9 | |
插入一个元素¶
定义 insert(o,v) 为在以 o 为根节点的二叉搜索树中插入一个值为 v 的新节点。
分类讨论如下:
若 o 为空,直接返回一个值为 v 的新节点。
若 o 的权值等于 v,该节点的附加域该值出现的次数自增 1。
若 o 的权值大于 v,在 o 的左子树中插入权值为 v 的节点。
若 o 的权值小于 v,在 o 的右子树中插入权值为 v 的节点。
时间复杂度为 O(h)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
删除一个元素¶
定义 del(o,v) 为在以 o 为根节点的二叉搜索树中删除一个值为 v 的节点。
先在二叉搜索树中找到权值为 v 的节点,分类讨论如下:
若该节点的附加 \textit{cnt} 大于 1,只需要减少 \textit{cnt}。
若该节点的附加 \textit{cnt} 为 1:
若 o 为叶子节点,直接删除该节点即可。
若 o 为链节点,即只有一个儿子的节点,返回这个儿子。
若 o 有两个非空子节点,一般是用它左子树的最大值或右子树的最小值代替它,然后将它删除。
时间复杂度 O(h)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |
求元素的排名¶
排名定义为将数组元素排序后第一个相同元素之前的数的个数加一。
查找一个元素的排名,首先从根节点跳到这个元素,若向右跳,答案加上左儿子节点个数加当前节点重复的数个数,最后答案加上终点的左儿子子树大小加一。
时间复杂度 O(h)。
1 2 3 4 5 | |
查找排名为 k 的元素¶
在一棵子树中,根节点的排名取决于其左子树的大小。
若其左子树的大小大于等于 k,则该元素在左子树中;
若其左子树的大小在区间 [k-\textit{cnt},k-1](\textit{cnt} 为当前结点的值的出现次数)中,则该元素为子树的根节点;
若其左子树的大小小于 k-\textit{cnt},则该元素在右子树中。
时间复杂度 O(h)。
1 2 3 4 5 6 | |
build本页面最近更新:,更新历史
edit发现错误?想一起完善? 在 GitHub 上编辑此页!
people本页面贡献者:OI-wiki
copyright本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用