Python之AVL树

Python之AVL树,第1张

文章目录
    • 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分

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/722444.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-26
下一篇 2022-04-26

发表评论

登录后才能评论

评论列表(0条)

保存