Python之AVL树

AVL树(平衡二叉树)

方法功能
find(data)查找值为data的节点是否存在树中
height()返回当前树高
insert(data)插入值为data的节点
delete(data)删除值为data的节点
get_pre(root)返回root节点的前驱
inorder(root)中序遍历
#节点类。AVL树相对一般二叉搜索树,节点增加树高属性,便于判断是否平衡,从而决定是否进行调整等。
class Node:
    def __init__(self, data = -1, height = 1, left = None, right = None):
        self.data = data
        self.left = left
        self.right = right
        self.height = height
    def __str__(self):
        return str(self.data)

class AVLTree:
    def __init__(self, root=None):
        self.root = root

    # 增加一些公有私有机制
    def find(self, data):
        if self.root == None:
            return None
        return self.__find(self.root, data)

    def __find(self, root, data):
        if root == None:
            return None
        if root.data == data:
            return root
        elif root.data < data:
            return self.__find(root.right, data)
        else:
            return self.__find(root.left, data)

    def height(self):
        if self.root == None:
            return 0
        return self.root.height

    def __update(self, root):
        root.height = 1
        if root.left != None:
            root.height = max(root.height, root.left.height + 1)
        if root.right != None:
            root.height = max(root.height, root.right.height + 1)

    def __left_rotate(self, root):
        tmp = root.right
        root.right = tmp.left
        tmp.left = root
        self.__update(root)
        self.__update(tmp)
        return tmp

    def __right_rotate(self, root):
        tmp = root.left
        root.left = tmp.right
        tmp.right = root
        self.__update(root)
        self.__update(tmp)
        return tmp

    def get_pre(self, root):
        tmp = root.left
        while tmp.right != None:
            tmp = tmp.right
        return tmp

    def insert(self, data):
        self.root = self.__insert(self.root, data)

    def __insert(self, root, data):
        if root == None:
            return Node(data)
        if root.data == data:
            return root
        if root.data < data:
            root.right = self.__insert(root.right, data)
        else:
            root.left = self.__insert(root.left, data)
        self.__update(root)
        return self.__maintain(root)

    def delete(self, data):
        self.root = self.__delete(self.root, data)

    def __delete(self, root, data):
        if root == None:
            return root
        if root.data < data:
            root.right = self.__delete(root.right, data)
        elif root.data > data:
            root.left = self.__delete(root.left, data)
        else:
            if root.left == None or root.right == None:
                tmp = root.left if root.left != None else root.right
                del root
                return tmp
            tmp = self.get_pre(root)
            root.data = tmp.data
            root.left = self.__delete(root.left, tmp.data)
        self.__update(root)
        return self.__maintain(root)

    def __maintain(self, root):
        left_h = root.left.height if root.left != None else 0
        right_h = root.right.height if root.right != None else 0
        if abs(left_h - right_h) <= 1:
            return root
        if left_h > right_h:
            lright_h = root.left.right.height if root.left.right != None else 0
            lleft_h = root.left.left.height if root.left.left != None else 0
            if lright_h > lleft_h:
                root.left = self.__left_rotate(root.left)
            root = self.__right_rotate(root)
        else:
            rleft_h = root.right.left.height if root.right.left != None else 0
            rright_h = root.right.right.height if root.right.right != None else 0
            if rleft_h > rright_h:
                root.right = self.__right_rotate(root.right)
            root = self.__left_rotate(root)
        return root

    def inorder(self, root):
        if root is None:
            return []
        res = [root.data]
        left_res = self.inorder(root.left)
        right_res = self.inorder(root.right)
        return left_res + res + right_res

测试代码:

t = AVLTree()
def printf():
    res = t.inorder(t.root)
    for i in res:
        print("{0}:({1}, {2})".format(t.find(i), t.find(i).left, t.find(i).right))
    print("root =", t.root, "h =", t.height())
    print()

for i in range(1, 10):
    t.insert(i)
    printf()

总结

这里的写法有点臃肿,主要是对于不存在的节点None,取不到height属性。所以对此需要if特判,取得默认None情况的height为0值。

然后就是平衡二叉树,基操就是进行旋转,回溯过程中,哪个地方不平衡了就立即调整,其它都同正常的BST。

还有一点就是写法问题,这次是用了_+name的形式书写方法名,化作私有方法,简而言之就是进行了多一层的封装,对外接口更加方便。对比上一个BST,我将节点的增删改查等方法以静态方法的形式,封装在Node类中,应该是各有优势吧。(不是


下一篇进攻树,对问题一的写法会有一个优化。话说就是这脑瘫的写法,搞得我debug半个钟。(节点树高的维护出错了,原因是__update() 方法中没加赋值那条语句)


2022年4月13日22点10分
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ღCauchyོꦿ࿐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值