二叉树bst

二叉搜索树的中序遍历结果有序 ,二叉搜索树性质,左小右大,二叉搜索树中序遍历的结果应该是从小到大的。

题目描述二叉树是从上到下,从左到右描述,并非前中后序中的一种。

99. 恢复二叉搜索树

class Solution:
    first = None 
    second = None 
    prev = TreeNode(float('-inf')) #这样对类进行初始化也是可以的,函数中要使用用self.调用     实例属性,实例方法

    def recoverTree(self, root: Optional[TreeNode]) -> None:
        """
        Do not return anything, modify root in-place instead.
        """  #原地修改,不要返回
        self.inorderTraverse(root)

        temp = self.first.val 
        self.first.val = self.second.val 
        self.second.val = temp 
    def inorderTraverse(self, root):
        if root is None:
            return 
        self.inorderTraverse(root.left)
        if root.val < self.prev.val:
            if self.first is None:
                self.first = self.prev
            self.second = root #本应该递增,变成了递减    打草稿可知道位置在哪
        self.prev = root #中序位置,更新结点   #由于更换了位置,第一个不符合条件的位于指针的prev位置,第二个不符合条件的位于root位置
        self.inorderTraverse(root.right)

669. 修剪二叉搜索树

class Solution:
    # 定义:删除 BST 中小于 low 和大于 high 的所有节点,返回结果 BST
    def trimBST(self, root: TreeNode, low: int, high: int) -> TreeNode:
        if root is None:
            return None

        if root.val < low:
            # 直接返回 root.right
            # 等于删除 root 以及 root 的左子树
            return self.trimBST(root.right, low, high)
        if root.val > high:
            # 直接返回 root.left
            # 等于删除 root 以及 root 的右子树
            return self.trimBST(root.left, low, high)

        # 闭区间 [lo, hi] 内的节点什么都不做,题目给的是闭区间  分解问题解法
        root.left = self.trimBST(root.left, low, high)
        root.right = self.trimBST(root.right, low, high)

        return root

明确了递归函数的定义之后进行思考,如果一个节点的值没有落在 [lo, hi] 中,有两种情况:

1、root.val < lo,这种情况下 root 节点本身和 root 的左子树全都是小于 lo 的,都需要被剪掉

2、root.val > hi,这种情况下 root 节点本身和 root 的右子树全都是大于 hi 的,都需要被剪掉

671. 二叉树中第二小的节点

class Solution:
    def findSecondMinimumValue(self, root: Optional[TreeNode]) -> int:
        if root.left is None and root.right is None:
            return -1 
            #只有一个结点,肯定没有第二小结点,  base case 
        left ,right = root.left.val, root.right.val 
        if root.val == root.left.val:
            left = self.findSecondMinimumValue(root.left) #在左边找第二小的节点值
        if root.right == root.right.val:
            right = self.findSecondMinimumValue(root.right) #在右边找第二小的节点值
        if left == -1:  #只要一边是叶子节点,就返回另一边找到的第二小值就可以 在最后在进行一个比较
            return right
        if right == -1:
            return left 
        return min(left,right) 

把题目理解清楚,把解决问题,定义的函数解决清楚,弄明白分解问题逻辑

这种自底向上的处理方式确保了我们在处理每个节点时,已经拥有了其左右子树的所有信息,可以直接进行计算,而不需要重复访问子树,从而提高了效率。 后序位置的优势、 后序遍历是“自底向上”的遍历方式,即:

  1. 先递归地遍历左子树,
  2. 再递归地遍历右子树,
  3. 最后处理当前节点(根节点)。

这种遍历方式意味着我们在处理一个节点时,已经处理并得到它的左右子树的结果。 “自底向上”的处理方式指的是在后序遍历过程中,我们在处理一个节点时,已经处理并完成了其所有子节点的操作。换句话说,当我们处理一个节点时,左右子树已经完全处理完毕,我们可以直接利用这些子树的结果进行进一步的计算。

在剪枝问题中,后序遍历是一种非常有效的方法,因为它可以确保在处理一个节点之前,已经处理完它的左右子树。这意味着我们可以从叶子节点开始,逐层向上剪枝,而不会影响未处理的节点。具体来说,后序遍历的顺序是“左子树 -> 右子树 -> 根节点”,这让我们能够自底向上地处理和剪枝。下面我们详细解释一下为什么后序遍历位置可以实现这种高效的剪枝 在整个过程中,我们每次处理节点时,都能确保它的左右子树已经处理完毕,这样我们可以根据子树的结果决定是否剪掉当前节点。这种方法确保了我们不会遗漏任何需要剪掉的节点,并且不会重复处理已经剪掉的部分,达到了最高的效率。

814. 二叉树剪枝

class Solution:
    def pruneTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        #定义,输入二叉树,返回二叉树叶子节点都是1
        if root is None:
            return None 
        root.left = self.pruneTree(root.left)
        root.right = self.pruneTree(root.right)  #是用分解问题的思路来做
        #后序位置的优越性,自下而上的处理方式,处理根节点时,左右结点已经处理
        if root.val ==  and root.left is None and root.right is None:
            return None #只有从后续遍历位置  并且要一直减枝
        return root 

生成二叉树的题目,无非就是先生成根节点,然后递归生成左右子树,最后把根节点和左右子树连接起来。具体区别在于你如何找到根节点,如何划分左右子树

1008. 前序遍历构造二叉搜索树

class Solution:
    def bstFromPreorder(self, preorder: List[int]) -> Optional[TreeNode]:
        return self.build(preorder, 0, len(preorder) - 1)
    #定义:将preorder[start, end]区间内的元素生成bst,并且返回根节点
    def build(self, preorder, start, end) :
        if start > end:
            return None 
        rootVal = preorder[start]
        root = TreeNode(rootVal)

        #p是左右子树的分界点      要构造树
        p = start + 1 
        while p <= end and preorder[p] < rootVal:
            p += 1   #找到第一个>根节点的值
        root.left = self.build(preorder, start + 1, p - 1)
        root.right = self.build(preorder ,p, end) 
        return root
  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您实现搜索二叉树BST)以及相关的操作。 首先,让我们定义一个BST节点的结构体: ``` typedef struct node { int key; struct node *left; struct node *right; } node_t; ``` 这个结构体包括了节点的值(key)以及左右子节点的指针。现在我们可以定义一个BST的结构体,这个结构体包含了BST的根节点指针: ``` typedef struct bst { node_t *root; } bst_t; ``` 现在,我们可以实现以下操作: 1. 创建一个新的节点 ``` node_t *new_node(int key) { node_t *node = (node_t *) malloc(sizeof(node_t)); node->key = key; node->left = NULL; node->right = NULL; return node; } ``` 2. 向BST中插入一个节点 ``` void insert(bst_t *bst, int key) { node_t *parent = NULL; node_t *current = bst->root; while (current != NULL) { parent = current; if (key < current->key) { current = current->left; } else { current = current->right; } } node_t *node = new_node(key); if (parent == NULL) { bst->root = node; } else if (key < parent->key) { parent->left = node; } else { parent->right = node; } } ``` 3. 获取BST的最小值 ``` node_t *min_value(node_t *node) { while (node->left != NULL) { node = node->left; } return node; } int get_min(bst_t *bst) { return min_value(bst->root)->key; } ``` 4. 获取BST的最大值 ``` node_t *max_value(node_t *node) { while (node->right != NULL) { node = node->right; } return node; } int get_max(bst_t *bst) { return max_value(bst->root)->key; } ``` 5. 在BST中搜索一个节点 ``` node_t *search(node_t *node, int key) { if (node == NULL || node->key == key) { return node; } if (key < node->key) { return search(node->left, key); } return search(node->right, key); } node_t *get_node(bst_t *bst, int key) { return search(bst->root, key); } ``` 6. 获取一个节点的前驱节点 ``` node_t *predecessor(node_t *node) { if (node == NULL) { return NULL; } if (node->left != NULL) { return max_value(node->left); } node_t *parent = node->parent; while (parent != NULL && node == parent->left) { node = parent; parent = parent->parent; } return parent; } node_t *get_predecessor(bst_t *bst, int key) { node_t *node = get_node(bst, key); if (node == NULL) { return NULL; } return predecessor(node); } ``` 7. 前序遍历BST ``` void preorder(node_t *node) { if (node != NULL) { printf("%d ", node->key); preorder(node->left); preorder(node->right); } } void traverse_preorder(bst_t *bst) { preorder(bst->root); } ``` 现在,我们已经成功地实现了搜索二叉树以及相关操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值