二叉搜索树简介
二叉搜索树简介¶
二叉搜索树是一种二叉树的树形数据结构,其定义如下:
空树是二叉搜索树。
若二叉搜索树的左子树不为空,则其左子树上所有点的附加权值均小于其根节点的值。
若二叉搜索树的右子树不为空,则其右子树上所有点的附加权值均大于其根节点的值。
二叉搜索树的左右子树均为二叉搜索树。
二叉搜索树上的基本操作所花费的时间与这棵树的高度成正比。对于一个有
基本操作¶
遍历二叉搜索树¶
由二叉搜索树的递归定义可得,二叉搜索树的中序遍历权值的序列为非降的序列。时间复杂度为
遍历一棵二叉搜索树的代码如下:
1 2 3 4 5 6 7 | void print(int o) //遍历以 o 为根节点的二叉搜索树 { if (!o) return; //遇到空树,返回 print(lc[o]); //递归遍历左子树 printf("%d\n", val[o]); //输出根节点信息 print(rc[o]); //递归遍历右子树 } |
查找最小/最大值¶
由二叉搜索树的性质可得,二叉搜索树上的最小值为二叉搜索树左链的顶点,最大值为二叉搜索树右链的顶点。时间复杂度为
1 2 3 4 5 6 7 8 | int findmin(int o) { if (!lc[o]) return val[o]; return findmin(lc[o]); //一直向左儿子跳 } int findmax(int o) { if (!rc[o]) return val[o]; return findmax(rc[o]); //一直向右儿子跳 } |
插入一个元素¶
定义 insert(o,v)
为在以
分类讨论如下:
若
若
若
若
时间复杂度为
1 2 3 4 5 6 7 8 9 10 | void insert(int o, int v) { if (!o) return; siz[o]++; if (val[o] > v) insert(lc[o], v); if (val[o] == v) { cnt[o]++; return; } if (val[o] < v) insert(rc[o], v); } |
删除一个元素¶
定义 delete(o,v)
为在以
先在二叉搜索树中找到权值为
若该节点的附加
若
若
若
时间复杂度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | int deletemin(int o) { if (!lc[o]) int ret = val[o], o = rc[o], return ret; else return deletemin(lc[o]); } void delete (int& o, int v) { siz[o]--; if (val[o] == v) { if (lc[o] && rc[o]) o = deletemin(rc[o]); else o = lc[o] + rc[o]; return; } if (val[o] > v) delete (lc[o], v); if (val[o] < v) delete (rc[o], v); } |
求元素的排名¶
排名定义为将数组元素排序后第一个相同元素之前的数的个数
维护每个根节点的子树大小
时间复杂度
1 2 3 4 5 | int queryrnk(int o, int v) { if (val[o] == v) return siz[lc[o]] + 1; if (val[o] > v) return queryrnk(lc[o], v); if (val[o] < v) return queryrnk(rc[o], v) + siz[lc[o]] + cnt[o]; } |
查找排名为 k 的元素¶
在一棵子树中,根节点的排名取决于其左子树的大小。
若其左子树的大小大于等于
若其左子树的大小在区间
若其左子树的大小小于
时间复杂度
1 2 3 4 5 6 | int querykth(int o, int k) { if (siz[lc[o]] >= k) return querykth(lc[o], k); if (siz[lc[o]] < k + cnt - 1) return querykth(rc[o], k - siz[lc[o]] - cnt[o] + 1); return o; } |
build本页面最近更新:,更新历史
edit发现错误?想一起完善? 在 GitHub 上编辑此页!
people本页面贡献者:
copyright本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用