zoukankan      html  css  js  c++  java
  • AVL树(平衡二叉树)

    定义及性质

      AVL树:AVL树是一颗自平衡的二叉搜索树.

      AVL树具有以下性质:

        根的左右子树的高度只差的绝对值不能超过1

        根的左右子树都是 平衡二叉树(AVL树)

    百度百科:

      平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法)

        且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

        平衡二叉树的常用实现方法有红黑树AVL替罪羊树Treap伸展树等。

           最小二叉平衡树的节点总数的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列

           可以参考Fibonacci(斐波那契)数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。

    AVL树--插入操作

    AVL插入--旋转

    代码实现

    from bst import BST, BiTreeNode
    
    
    class AVLNode(BiTreeNode):
        def __init__(self, data):
            BiTreeNode.__init__(self, data)
            self.bf = 0
    
    
    class AVLTree(BST):
        def __init__(self, li=None):
            BST.__init__(self, li)
    
        def rotate_left(self, p, c):
            s2 = c.lchild
            p.rchild = s2
            if s2:
                s2.parent = p
    
            c.lchild = p
            p.parent = c
    
            # 更新bf
            if c.bf == 0:
                p.bf = 1
                c.bf = -1
            else:
                p.bf = 0
                c.bf = 0
            return c
    
        def rotate_right(self, p, c):
            s2 = c.rchild
            p.lchild = s2
            if s2:
                s2.parent = p
    
            c.rchild = p
            p.parent = c
    
            # update bf
            if c.bf == 0:
                p.bf = -1
                c.bf = 1
            else:
                p.bf = 0
                c.bf = 0
            return c
    
        def rotate_right_left(self, p, c):
            g = c.lchild
    
            s3 = g.rchild
            c.lchild = s3
            if s3:
                s3.parent = c
            g.rchild = c
            c.parent = g
    
            s2 = g.lchild
            p.rchild = s2
            if s2:
                s2.parent = p
            g.lchild = p
            p.parent = g
    
            # 更新 bf
            if g.bf > 0:  # g.bf == 1
                p.bf = -1
                c.bf = 0
            elif g.bf == 0:
                p.bf = 0
                c.bf = 0
            else: # g.bf == -1
                p.bf = 0
                c.bf = 1
    
            g.bf = 0
            return g
    
        def rotate_left_right(self, p, c):
            g = c.rchild
    
            s3 = g.lchild
            c.rchild = s3
            if s3:
                s3.parent = c
            g.lchild = c
            c.parent = g
    
            s2 = g.rchild
            p.lchild = s2
            if s2:
                s2.parent = p
            g.rchild = p
            p.parent = g
    
            # 更新 bf
            if g.bf < 0:  # g.bf == 1
                p.bf = 1
                c.bf = 0
            elif g.bf == 0:
                p.bf = 0
                c.bf = 0
            else:  # g.bf == -1
                p.bf = 0
                c.bf = -1
    
            g.bf = 0
            return g
    
    
    
        def insert_no_rec(self, val):
            p = self.root
            if not p:
                self.root = AVLNode(val)
                return
            while True:
                if val < p.data:
                    if p.lchild:
                        p = p.lchild
                    else:
                        p.lchild = AVLNode(val)
                        p.lchild.parent = p
                        node = p.lchild
                        break
                elif val > p.data:
                    if p.rchild:
                        p = p.rchild
                    else:
                        p.rchild = AVLNode(val)
                        p.rchild.parent = p
                        node = p.rchild
                        break
                else:
                    return
    
            # 更新bf
            while node.parent:
                if node.parent.lchild == node:  # 左孩子
                    if node.parent.bf < 0: # node.parent.bf=-2 左边深
                        g = node.parent.parent
                        if node.bf > 0:
                            n = self.rotate_left_right(node.parent, node)
                        else:
                            n = self.rotate_right(node.parent, node)
                    elif node.parent.bf > 0:
                        node.parent.bf = 0
                        break
                    else:
                        node.parent.bf = -1
                        node = node.parent
                        continue
    
                else:  # 右孩子
                    if node.parent.bf > 0: # node.parent.bf=2 右边深
                        g = node.parent.parent
                        if node.bf < 0:
                            n = self.rotate_right_left(node.parent, node)
                        else:
                            n = self.rotate_left(node.parent, node)
                    elif node.parent.bf < 0:
                            node.parent.bf = 0
                            break
                    else:
                        node.parent.bf = 1
                        node = node.parent
                        continue
    
                # 旋转结束后
                # 连接旋转后的子树的根和原来的树
    
                n.parent = g
                if g:
                    if node.parent == g.lchild:
                        g.lchild = n
                    else:
                        g.rchild = n
                    break
                else:
                    self.root = n
                    break
    
    
    
    tree = AVLTree([7,3,5,4,2,8,6,9,1])
    tree.pre_order(tree.root)
    print("")
    tree.in_order(tree.root)
  • 相关阅读:
    bootstrap实战练习中涉及的知识点(很有用哦!)
    Markdown的最常用标记符号有哪些?
    队列的插入 和出列 阻塞 时间 问题
    ArrayBlockingQueue和LinkedBlockingQueue的使用
    自己总结 :并发队列ConcurrentLinkedQueue、阻塞队列AraayBlockingQueue、阻塞队列LinkedBlockingQueue 区别 和 使用场景总结
    战斗由客户端来做,后端来验证 方式 解决 一些弊端思路
    类 文件 右下角呈现 红色小圆圈,里面有一个J 标记
    苏州儿童医保
    Error: opening registry key 'SoftwareJavaSoftJava Runtime Environment' could not find java.dll
    intellj(idea) 编译项目时在warnings 页签框里 报 “xxx包不存在” 或 “找不到符号” 或 “未结束的字符串字面值” 或 “需要)” 或 “需要;”等错误提示
  • 原文地址:https://www.cnblogs.com/xiao-xue-di/p/10169711.html
Copyright © 2011-2022 走看看