AVL数的建立

AVL树是一种自平衡二叉搜索树,确保每个节点的左右子树高度差不超过1。当节点高度差达到2时,需要进行自平衡调整。删除操作分为三种情况:删除叶子节点、只有一个子树的节点和拥有两个子树的节点。删除后需更新平衡因子并进行必要的平衡旋转。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AVL数是一棵自平衡的二叉搜索树。数的每一个节点的左右子树高度差绝对值不能超过1.

如果某一个节点的左右子树的高度差绝对值等于2时,则二叉树需要自平衡操作:

 

 

 

class BiTreeNode():         # 定义二叉树型节点
    def __init__(self,val):
        self.data = val
        self.lchild = None
        self.rchild = None
        self.parent = None
        self.bf = None

class AVLTree():            # 定义AVL数对象
    def __init__(self):
        self.root = None

    def node_depth(self,node):      # 计算以节点node为根的数高度
        if not node:
            return 0
        if not node.lchild and not node.rchild:
            return 1
        else:
            ml = self.node_depth(node.lchild)+1
            mr = self.node_depth(node.rchild)+1
        return max(ml,mr)

    def bf_update(self,node):       # 更新节点的balance factor
        flag_change2zero = 0
        if not node:
            return 0, flag_change2zero
        else:
            ml = self.node_depth(node.lchild)
            mr = self.node_depth(node.rchild)
            bf = ml - mr
        if node.bf and bf == 0:     # 如果该节点的bf变化为0,则该节点的父节点的bf值将不受影响
            flag_change2zero = 1
        return bf,flag_change2zero

    def rotate_left(self,node_f,node_s):    # 左旋
        if node_f.parent:       # 判断旋转之前的node_f节点是否有父节点,有的话需要将旋转后的节点与父节点相连
            node_gf = node_f.parent
        else:
            node_gf = None
        node_gs = node_s.lchild
        node_f.rchild = node_gs
        if node_gs:
            node_gs.parent = node_f
        node_s.lchild = node_f
        node_f.parent = node_s
        return node_s,node_gf

    def rotate_right(self,node_f,node_s):   # 右旋
        if node_f.parent:
            node_gf = node_f.parent
        else:
            node_gf = None
        node_gs = node_s.rchild
        node_f.lchild = node_gs
        if node_gs:
            node_gs.parent = node_f
        node_s.rchild = node_f
        node_f.parent = node_s
        return node_s,node_gf

    def rotate_right_left(self,node_f,node_s):      # 先右旋再左旋
        if node_f.parent:
            node_gf = node_f.parent
        else:
            node_gf = None
        node_gs = node_s.lchild
        node_ggs = node_gs.rchild
        node_s.lchild = node_ggs
        if node_ggs:
            node_ggs.parent = node_s
        node_gs.rchild = node_s
        node_s.parent = node_gs

        node_ggs = node_gs.lchild
        node_f.rchild = node_ggs
        if node_ggs:
            node_ggs.parent = node_f
        node_gs.lchild = node_f
        node_f.parent = node_gs
        return node_gs,node_gf

    def rotate_left_right(self,node_f,node_s):      # 先左旋再右旋
        if node_f.parent:
            node_gf = node_f.parent
        else:
            node_gf = None
        node_gs = node_s.rchild
        node_ggs = node_gs.lchild
        node_s.rchild = node_ggs
        if node_ggs:
            node_ggs.parent = node_s
        node_gs.lchild = node_s
        node_s.parent = node_gs

        node_ggs = node_gs.rchild
        node_f.lchild = node_ggs
        if node_ggs:
            node_ggs.parent = node_f
        node_gs.rchild = node_f
        node_f.parent = node_gs
        return node_gs,node_gf

    def insert(self,val):       # 插入节点
        if not self.root:
            self.root = BiTreeNode(val)
            self.root.bf = 0
            return self.root
        node = self.root
        while True:
            if val < node.data:
                if node.lchild:
                    node = node.lchild
                else:
                    node_new = BiTreeNode(val)
                    node.lchild = node_new
                    node_new.parent = node
                    break
            else:
                if node.rchild:
                    node = node.rchild
                else:
                    node_new = BiTreeNode(val)
                    node.rchild = node_new
                    node_new.parent = node
                    break
        node = node_new
        node_order = []     # 用来表示引起变化的节点的来源,来源于左子树,存1,来源与右子树,存-1
        flag_rotate = 0
        while True:     # 节点插入完毕后对节点的bf进行更新。
            node.bf, flag_change2zero = self.bf_update(node)
            if node.bf == -2 or node.bf == 2:   # 遇到某一节点的bf变为2或-2时,停止更新,进行自平衡操作。
                node_f = node
                flag_rotate = 1
                break
            if not node.parent or flag_change2zero == 1:    # 更新到根节点或某一节点的bf变为0,则停止更新。
                break
            else:
                if node.parent.lchild == node:
                    node_order.append(1)
                else:
                    node_order.append(-1)
                node = node.parent
        if flag_rotate:     # 进行自平衡操作。
            if node_order[-1] == -1:
                if node_order[-2] == -1:    # 右右,要左旋
                    node, node_gf = self.rotate_left(node_f, node_f.rchild)
                    node.bf = self.bf_update(node)[0]
                    node.lchild.bf = self.bf_update(node.lchild)[0]
                else:       # 右左,先右旋,再左旋
                    node, node_gf = self.rotate_right_left(node_f,node_f.rchild)
                    node.bf = self.bf_update(node)[0]
                    node.lchild.bf = self.bf_update(node.lchild)[0]
                    node.rchild.bf = self.bf_update(node.rchild)[0]
            else:
                if node_order[-2] == 1:     # 左左,要右旋
                    node, node_gf = self.rotate_right(node_f, node_f.lchild)
                    node.bf = self.bf_update(node)[0]
                    node.rchild.bf = self.bf_update(node.rchild)[0]
                else:       # 左右,先左旋,再右旋
                    node, node_gf = self.rotate_left_right(node_f, node_f.lchild)
                    node.bf = self.bf_update(node)[0]
                    node.lchild.bf = self.bf_update(node.lchild)[0]
                    node.rchild.bf = self.bf_update(node.rchild)[0]
            if node_gf:     # 如果旋转之前的节点有父节点,进行父节点链接。
                if node_gf.lchild == node_f:
                    node_gf.lchild = node
                    node.parent = node_gf
                else:
                    node_gf.rchild = node
                    node.parent = node_gf
            else:       # 如果旋转之前的节点没有父节点,则root节点要在旋转之中,此时需要更新root节点
                node.parent = None
                self.root = node
        return self.root

    def pre_order(self,root):
        if root:
            print(root.data,root.bf, end='  ')
            self.pre_order(root.lchild)
            self.pre_order(root.rchild)

    def in_order(self,root):
        if root:
            self.in_order(root.lchild)
            print(root.data,root.bf, end='  ')
            self.in_order(root.rchild)

AVL数的搜索与删除操作与二叉搜索数一样。删除时需要考虑删除节点的类型:
(1)如果删除的节点为叶子节点,则直接删除。
(2)如果删除的节点只有左子树或右子树,将左子树或右子树直接连于删除节点的父节点,此时需要考虑删除节点是根节点的情况。
(3)如果删除节点有左子树和右子树,此时需要从删除节点的右子树中找值最小的节点放于删除节点的位置。

删除节点后,需要对删除后相关节点的bf进行更新,并进行自平衡操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值