二叉排序树(BST)

定义

二叉排序树是一种特殊的二叉树,其中左子树中的所有节点都小于根节点,右子树中的所有节点都大于根节点(如下图所示)。
因此构造过程需要确保插入的元素能够按照这个规则被正确地插入到树中
image

性质

1、如果初始状态是一个空树,则插入每个元素的时间复杂度是 O(log n),其中 n 是树中节点的数量。这是因为每次插入元素时,都需要从根节点开始,按照比较规则找到合适的位置插入,而树的高度是 log n!
2、如果初始状态的树不平衡,比如退化成链表,那么插入每个元素的时间复杂度可能接近 O(n),于是便有平衡树的诞生!
3、查找最小值,一直遍历左节点即可,反之则一直遍历右节点;若要查询元素x,可类比二分!

代码实现

# 二叉排序树的构建(BST)

class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None


class Tree:
    def __init__(self, root):
        self.root = root

    def create_bst(self, a):
        for x in a:
            self.insert_node(x)

    def insert_node(self, data):
        node = Node(data)
        if self.root.data == -1:
            self.root = node
            return
        head = self.root
        while 1:
            if data < head.data:
                if not head.left:
                    head.left = node
                    return
                else:
                    head = head.left
            else:
                if not head.right:
                    head.right = node
                    return
                else:
                    head = head.right

    def delete_node(self, data):
        # 定位节点及其父节点的位置
        cur = self.root
        left_flag = True
        pa = self.root
        while cur.data != data:
            if data <= cur.data:
                if cur.left:
                    pa = cur
                    cur = cur.left
                    left_flag = True
            else:
                if cur.right:
                    pa = cur
                    cur = cur.right
                    left_flag = False
            if not cur:
                return False
        # 情况1:叶子节点
        if not cur.left and not cur.right:
            if cur == self.root:
                self.root.data = -1
            elif left_flag:
                pa.left = None
            else:
                pa.right = None

        # 情况2:只有左节点
        elif not cur.right:
            if cur == self.root:
                self.root = cur.left
            elif left_flag:
                pa.left = cur.left
            else:
                pa.right = cur.left
        # 情况3:只有右节点
        elif not cur.left:
            if cur == self.root:
                self.root = cur.left
            elif left_flag:
                pa.left = cur.right
            else:
                pa.right = cur.right

        # 情况4:既有左节点,又有右节点
        else:
            # tmp为直接前驱,pa_tmp为双亲
            # 比如 1 2 3 4 5 6 7,我们要删除6,那么在树中找到5对应的节点!
            tmp = cur.left
            pa_tmp = cur
            while tmp.right:
                pa_tmp = tmp
                tmp = tmp.right
            cur.data = tmp.data

            # 如果cur的第一个左节点就没有右节点
            if pa_tmp == cur:
                pa_tmp.left = tmp.left
            else:
                pa_tmp.right = tmp.left

    def printf(self):
        ans = []

        def dfs(root):
            if not root:
                return
            dfs(root.left)
            ans.append(root.data)
            dfs(root.right)

        dfs(self.root)
        print(*ans)


a = [5, 7, 6, 2, 1]
mytree = Tree(Node(-1))
mytree.create_bst(a)
mytree.printf()
mytree.delete_node(6)
mytree.printf()
mytree.insert_node(100)
mytree.printf()

posted @ 2024-04-08 09:04  gebeng  阅读(58)  评论(0)    收藏  举报