二叉排序树(BST)

二叉排序树

基本介绍

二叉排序树创建和遍历

class Node:
    """
    创建 Node 节点
    """
    value: int = 0
    left = None
    right = None

    def __init__(self, value: int):
        self.value = value

    def add(self, node):
        """
        添加节点
        node 表示要添加的节点
        """
        if node is None:
            return
        # 判断要添加节点和当前子树根节点的大小
        if node.value < self.value:
            # 要添加节点小于当前子树根节点
            if self.left is None:
                # 如果当前子树左子节点为空,则直接将要添加的节点挂在左子节点上
                self.left = node
            else:
                # 否则,递归当前子树的左节点,找到要放置的位置
                self.left.add(node)
        else:  # 要添加节点大于等于当前子树根节点
            if self.right is None:
                # 如果当前子树右子节点为空,则直接将要添加的节点挂在右子节点上
                self.right = node
            else:
                # 否则,递归当前子树的右节点,找到要放置的位置
                self.right.add(node)

    def infix_order(self):
        """
        中序遍历二叉树
        """
        if self.left:
            self.left.infix_order()
        print(self.value)
        if self.right:
            self.right.infix_order()


class BinarySortTree:
    """
    二叉排序树
    """
    root: Node = None

    def add(self, node: Node):
        """
        添加节点
        node: 要添加的节点
        """
        if self.root is None:
            # 如果根节点为空,直接将新节点当做根节点
            self.root = node
        else:
            # 否则,将新节点放在根节点下
            self.root.add(node)

    def infix_order(self):
        """
        中序遍历
        """
        if self.root:
            self.root.infix_order()
        else:
            print("二叉排序树为空...")


arr = [7, 3, 10, 12, 5, 1, 9]
binary_sort_tree = BinarySortTree()
for i in arr:
    node = Node(i)
    binary_sort_tree.add(node)
binary_sort_tree.infix_order()

二叉排序树的节点删除

思路分析

代码实现

"""二叉排序树"""
class Node:
    """
    创建 Node 节点
    """
    value: int = 0
    left = None
    right = None

    def __init__(self, value: int):
        self.value = value



    def add(self, node):
        """
        添加节点
        node 表示要添加的节点
        """
        if node is None:
            return
        # 判断要添加节点和当前子树根节点的大小
        if node.value < self.value:
            # 要添加节点小于当前子树根节点
            if self.left is None:
                # 如果当前子树左子节点为空,则直接将要添加的节点挂在左子节点上
                self.left = node
            else:
                # 否则,递归当前子树的左节点,找到要放置的位置
                self.left.add(node)
        else:  # 要添加节点大于等于当前子树根节点
            if self.right is None:
                # 如果当前子树右子节点为空,则直接将要添加的节点挂在右子节点上
                self.right = node
            else:
                # 否则,递归当前子树的右节点,找到要放置的位置
                self.right.add(node)

    def infix_order(self):
        """
        中序遍历二叉树
        """
        if self.left:
            self.left.infix_order()
        print(self.value)
        if self.right:
            self.right.infix_order()

    def search_delete(self, value: int):
        """
        查找要删除的节点
        :param value: 要删除节点的值
        :return:
        """
        if self.value == value:  # 当前节点就是要找的删除的节点,返回
            return self
        elif value < self.value:  # 要删除的值小于当前节点的值,则在当前节点的左子树递归查找
            if self.left:
                return self.left.search_delete(value)
            return None
        else:  # 要删除的值大于当前节点的值,则在当前节点的右子树递归查找
            if self.right:
                return self.right.search_delete(value)
            return None

    def find_parent(self, value: int):
        """
        查找要删除节点的父节点
        :param value: 要删除的节点值
        :return:
        """
        if (self.left and self.left.value == value or
                self.right and self.right.value == value):
            return self
        else:
            # 如果要删除的值小于当前节点的值,且当前节点有左节点,则向左节点递归查找
            if value < self.value and self.left:
                return self.left.find_parent(value)
            # 如果要删除的值大于等于当前节点的值,且当前节点有右节点,则向右 节点递归查找
            elif value >= self.value and self.right:
                return self.right.find_parent(value)
            return None  # 没有找到父节点,返回空,表示没有父节点,即要删除的是根节点


class BinarySortTree:
    """
    二叉排序树
    """
    root: Node = None

    def add(self, node: Node):
        """
        添加节点
        node: 要添加的节点
        """
        if self.root is None:
            # 如果根节点为空,直接将新节点当做根节点
            self.root = node
        else:
            # 否则,将新节点放在根节点下
            self.root.add(node)

    def infix_order(self):
        """
        中序遍历
        """
        if self.root:
            self.root.infix_order()
        else:
            print("二叉排序树为空...")

    def search_delete(self, value) -> Node:
        """
        查找要删除的节点
        :param value: 要删除节点的值
        :return:
        """
        if self.root:
            return self.root.search_delete(value)
        return None

    def find_parent(self, value) -> Node:
        """
        查找要删除节点的父节点
        :param value: 要删除节点的值
        :return:
        """
        if self.root:
            return self.root.find_parent(value)
        return None

    def find_and_delete_right_tree_min(self, node: Node) -> int:
        """
        查找以 node 为根节点的二叉排序树的最小节点
        返回小节点的值并从该二叉排序树中删除最小节点
        :param node:
        :return:
        """
        t = node
        while t.left:  # 因为要找最小节点,所以从二叉排序树的左子树中找
            t = t.left
        # 退出循环时,t 指向的就是最小节点
        val = t.value
        self.delete_node(val)
        return val

    def delete_node(self, value: int):
        """
        删除接地那
        :param value: 要删除节点的值
        :return:
        """
        if self.root is None:
            print("二叉树为空,不能删除节点...")
            return
        # 查找要删除的节点
        target_node = self.search_delete(value)
        if target_node is None:  # 找不到要删除的节点
            print(f"节点{value}不存在")
            return
        if self.root.left is None and self.root.right is None:
            # 此时找到了要删除的节点,且二叉树只有一个节点,所以要删除的就是这唯一的一个节点
            self.root = None
            return
        # 查找要删除节点的父节点
        parent = self.find_parent(value)
        if target_node.left is None and target_node.right is None:
            # 此时说明要删除的节点是叶子节点
            # 进一步判断要删除的节点是父节点的左节点还是右节点
            if parent.left and parent.left.value == value:
                # 说明要删除节点是父节点的左子节点
                parent.left = None
                return
            if parent.right and parent.right.value == value:
                # 说明要删除节点是父节点的右子节点
                parent.right = None
                return
        elif target_node.left and target_node.right:
            # 要删除的节点有左右两棵子树
            # 从要删除节点的右子树中找到最小节点,获得该最小节点的值并删除该最小节点
            # 然后将最小节点的值赋值给要删除节点
            min_val = self.find_and_delete_right_tree_min(target_node.right)
            target_node.value = min_val

            # 同理,也可以从要删除节点的左子树找到最大节点,获得该最大节点的值并删除该最大节点
            # 然后将最大节点的值赋值给要删除节点
        else:
            # 要删除的节点只有一棵子树
            # 进一步确定要删除节点的子树是左子树还是右子树
            if target_node.left:
                # 要删除节点的子树是左子树
                if parent is None:
                    # 如果父节点为空,说明要删除的是根节点,则直接让根基诶到哪等于它的左子节点
                    self.root = target_node.left
                # 进一步判断要删除的节点是父节点的左节点还是右节点
                elif parent.left.value == value:
                    # 要删除的节点是父节点的左节点
                    parent.left = target_node.left
                else:  # 要删除的节点是父节点的右节点
                    parent.right = target_node.left
            else:  # 要删除节点的子树是右子树
                if parent is None:
                    # 如果父节点为空,说明要删除的是根节点,则直接让根基诶到哪等于它的右子节点
                    self.root = target_node.right
                # 进一步判断要删除的节点是父节点的左节点还是右节点
                elif parent.left.value == value:
                    # 要删除的节点是父节点的左节点
                    parent.left = target_node.right
                else:  # 要删除的节点是父节点的右节点
                    parent.right = target_node.right


# 测试二叉排序树的创建和遍历
arr = [7, 3, 10, 12, 5, 1, 9, 2]
binary_sort_tree = BinarySortTree()
for i in arr:
    node = Node(i)
    binary_sort_tree.add(node)
binary_sort_tree.infix_order()
# 测试删除二叉排序树的结点
binary_sort_tree.delete_node(7)
print("删除节点后:")
binary_sort_tree.infix_order()

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值