平衡二叉树(AVL树)

平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。这个方案很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(logN)。但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了很多。

时间复杂度:AVL树的查找、插入和删除在平均和最坏情况下都是O(logn)

AVL树节点定义

class Node(object):
    def __init__(self, val, left=None, right=None, height=-1):
        self.val = val
        self.left = left
        self.right = right
        self.height = height

 

二叉平衡树失去平衡的情况和调整策略

1. LL

LeftLeft,也称为"左左"。插入或删除一个节点后,根节点的左子树的左子树还有非空子节点,导致"根的左子树的高度"比"根的右子树的高度"大2,导致AVL树失去了平衡。

def leftLeftRotate(self, node):
k = node.left
node.left = k.right
k.right = node
node.height = max(node.left.height, node.right.height) + 1
k.height = max(k.left.height, k.right.height) + 1
return k

 

2. RR

RightRight,称为"右右"。插入或删除一个节点后,根节点的右子树的右子树还有非空子节点,导致"根的右子树的高度"比"根的左子树的高度"大2,导致AVL树失去了平衡。

    def rightRightRotate(self, node):
        k = node.right
        node.right = k.left
        k.left = node
        node.height = max(node.left.height, node.right.height) + 1
        k.height = max(k.left.height, k.right.height) + 1
        return k

 

3. LR

LeftRight,也称为"左右"。插入或删除一个节点后,根节点的左子树的右子树还有非空子节点,导致"根的左子树的高度"比"根的右子树的高度"大2,导致AVL树失去了平衡。

    def leftRightRotate(self, node):
        node.left = self.rightRightRotate(node.left)
        return self.leftLeftRotate(node)

 

4. RL

RightLeft,称为"右左"。插入或删除一个节点后,根节点的右子树的左子树还有非空子节点,导致"根的右子树的高度"比"根的左子树的高度"大2,导致AVL树失去了平衡。

    def rightLeftRotate(self, node):
        node.right = self.leftLeftRotate(node.right)
        return self.rightRightRotate(node)

 

插入节点

    def insert(self, root, val):
        if root == None:
            root = Node(val = val, height = 0)
            return root
        if val < root.left:
            root.left = self.insert(root.left, val)
            if root.left.height - root.right.height == 2:  #在左子树插入节点,可能出现左比右高
                if val < root.left.val: #LL
                    root = self.leftLeftRotate(root)
                else:   #LR
                    root = self.leftRightRotate(root)
        else:
            root.right = self.insert(root.right, val)
            if root.right.height - root.left.height == 2:  #在右子树插入节点,可能出现右比左高
                if val < root.right.key: #RL
                    root = self.rightLeftRotate(root)
                else:   #RR
                    root = self.rightRightRotate(root)

        root.height = max(root.left.height, root.right.height) + 1
        return root

 

删除节点

def delNode(self, root, val):
        if root == None:
            return None
        if val < root.val:
            root.left = self.delNode(root.left, val)
            if root.right.height - root.left.height == 2:   #删除左子树中节点,可能出现右比左高
                if root.right.right.height >= root.right.left.height:
                    root = self.rightRightRotate(root)  #RR
                else:
                    root = self.rightLeftRotate(root)   #RL
        elif val > root.val:
            root.right = self.delNode(root.right, val)
            if root.left.height - root.right.height == 2:   #删除右子树中节点,可能出现左比右高
                if root.left.left.height >= root.left.right.height:
                    root = self.leftLeftRotate(root)    #LL
                else:
                    root = self.leftRightRotate(root)   #LR
        elif root.left and root.right:
            if root.left.height <= root.right.height:
                minNode = self.findMin(root.right)
                root.val = minNode.val
                root.right = self.delNode(root.right, minNode.val)
            else:
                maxNode = self.findMax(root.left)
                root.val = maxNode.val
                root.left = self.delNode(root.left, maxNode.val)
        else:
            if root.right:
                root = root.right
            else:
                root = root.left
        root.height = max(root.left.height, root.right.height) + 1

        return root

 

全部代码

class AVLTree(object):
    def LeftLeftRotate(self, node):
        k = node.left
        node.left = k.right
        k.right = node
        node.height = max(node.left.height, node.right.height) + 1
        k.height = max(k.left.height, k.right.height) + 1
        return k

    def rightRightRotate(self, node):
        k = node.right
        node.right = k.left
        k.left = node
        node.height = max(node.left.height, node.right.height) + 1
        k.height = max(k.left.height, k.right.height) + 1
        return k

    def leftRightRotate(self, node):
        node.left = self.rightRightRotate(node.left)
        return self.leftLeftRotate(node)

    def rightLeftRotate(self, node):
        node.right = self.leftLeftRotate(node.right)
        return self.rightRightRotate(node)

    def insert(self, root, val):
        if root == None:
            root = Node(val = val, height = 0)
            return root
        if val < root.left:
            root.left = self.insert(root.left, val)
            if root.left.height - root.right.height == 2:
                if val < root.left.val: #LL
                    root = self.leftLeftRotate(root)
                else:   #LR
                    root = self.leftRightRotate(root)
        else:
            root.right = self.insert(root.right, val)
            if root.right.height - root.left.height == 2:
                if val < root.right.key: #RL
                    root = self.rightLeftRotate(root)
                else:   #RR
                    root = self.rightRightRotate(root)

        root.height = max(root.left.height, root.right.height) + 1
        return root

    def delNode(self, root, val):
        if root == None:
            return None
        if val < root.val:
            root.left = self.delNode(root.left, val)
            if root.right.height - root.left.height == 2:   #删除左子树中节点,可能出现右比左高
                if root.right.right.height >= root.right.left.height:
                    root = self.rightRightRotate(root)  #RR
                else:
                    root = self.rightLeftRotate(root)   #RL
        elif val > root.val:
            root.right = self.delNode(root.right, val)
            if root.left.height - root.right.height == 2:   #删除右子树中节点,可能出现左比右高
                if root.left.left.height >= root.left.right.height:
                    root = self.leftLeftRotate(root)    #LL
                else:
                    root = self.leftRightRotate(root)   #LR
        elif root.left and root.right:
            if root.left.height <= root.right.height:
                minNode = self.findMin(root.right)
                root.val = minNode.val
                root.right = self.delNode(root.right, minNode.val)
            else:
                maxNode = self.findMax(root.left)
                root.val = maxNode.val
                root.left = self.delNode(root.left, maxNode.val)
        else:
            if root.right:
                root = root.right
            else:
                root = root.left
        root.height = max(root.left.height, root.right.height) + 1

        return root


    def findMin(self, root):
        if root == None:
            return None
        if root.left == None:
            return root
        return self.findMin(root.left)

    def findMax(self, root):
        if root == None:
            return None
        if root.right == None:
            return root
        return self.findMax(root.right)

 

参考博客

https://www.cnblogs.com/skywang12345/p/3576969.html

https://www.cnblogs.com/linxiyue/p/3659448.html?utm_source=tuicool&utm_medium=referral

posted @ 2019-07-03 09:47  xd_xumaomao  阅读(216)  评论(0编辑  收藏  举报