二叉搜索树
二叉搜索树的定义(性质):
二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于(等于)它的根节点的值;
(2)若右子树不空,则右子树上所有结点的值均大于(等于)它的根结点的值;
(3)左、右子树也分别为二叉搜索树;
例如:int a [] = {5,3,4,1,7,8,2,6,0,9};
物理结构如下:
下标 1, 2, 3, 4, 5, 6, 7, 8, 9,10
val[]={5, 3, 4, 1, 7, 8, 2, 6, 0,9}
ls[]= {2, 4, 0, 9, 8, 0, 0, 0, 0,0}
rs[]= {5, 3, 0, 7, 6,10, 0, 0, 0,0}
Root=1
对这树进行中序遍历可得到一个有序序列
查询操作:
若根结点的关键字值等于查找的关键字,返回根节点的值。
否则,若小于根结点的关键字值,递归查左子树。
若大于根结点的关键字值,递归查右子树。
若子树为空,则查找不成功。
二叉搜索树的插入:
与查询类似,判断在左子树还是右子树,走到叶节点后直接新加一个节点。
二叉搜索树的最值:
最小值:一直往左子树里找
最大值:一直往右子树里找
二叉搜索树的前驱/后继:
前驱是第一个比这个数小的值,后继是第一个比这个大的值
前驱:如果这个节点x有左子树,就以左儿子为根,查询左子树的最大值
如果没有左子树(1):如果x为右儿子,前驱就是x的父亲
(2):如果x为左儿子,前驱就是它的最靠近它的右子树的父结点
50的前驱是45。(前驱是左子树最大值)
45的前驱是40。(没有左子树且为右儿子,前驱是其父亲)
60的前驱是50。(没有左子树且为左儿子,前驱是其右父亲的左父亲)
30没有前驱。 【没有左子树且为左儿子,但在30的左父亲(祖先)里没有有左父亲的节点】
后继:如果这个节点有右子树,就以右儿子为根,查询右子树的最大值
如果没有右子树(1):如果x为左儿子,后继就是x的父亲
(2):如果x为右儿子,后继就是它的最靠近它的左子树的父结点
50的后继是60。(后继是右子树里最小的)
60的后继是65。(没有右子树且为左儿子,后继是其父亲)
45的后继是50。(没有右子树且为右儿子,后继是其左父亲的右父亲)
80无后继。 【没有右子树且为右儿子,但在80的左父亲(祖先)里没有有右父亲的节点】
二叉搜索树的删除:
删除有三种情况:
情况1:删除点为叶节点, 直接删除。
情况2:删除点右一个儿子, 直接用儿子替换删除点的位置
情况3:删除点右两个儿子
找到删除点的后继,用后继代替删除点,然后让后继的儿子替换后继的位置(情况2)
当序列是有序的时候进行插入操作是BST树就会退化成一条链,使得操作的时间复杂度变成O(n)。
练习题
P1177 【模板】快速排序(普及-)
P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G(普及/提高-)
P5076 【深基16.例7】普通二叉树(简化版)(普及+/提高)
P1296 奶牛的耳语(入门)
P3369 【模板】普通平衡树(提高+/省选-)
P2234 [HNOI2002]营业额统计(提高+/省选-)