淘先锋技术网

首页 1 2 3 4 5 6 7

key 关键字项
bf 平衡因子
data 其它数据域
lchild rchild 左右孩子


在这里插入图片描述

在这里插入图片描述

#右选 左旋
在这里插入图片描述
往右偏移说明插入在s3上了,s3s是h,s2是h-1

#左旋 右旋
在这里插入图片描述

#下面的代码是右边减左边,其实应该是左边减右边的

from bst import BiTreeNode,BST


#下面的代码是右边减左边,其实应该是左边减右边的

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的左子树
                s2 = c.lchild
                p.rchild =s2
                if s2:
                        #父亲连过来,孩子也要连回去
                        s2.parent = p
                c.lchild = p
                p.parent = c

                p.bf = 0
                c.bf = 0
                return c


        def insert_no_rec(self,val):
                s2 = c.rchild
                p.lchild = s2
                if s2:
                        s2.parent = p
                c.rchild = p
                p.parent = c
                p.bf = 0
                c.bf = 0
                return c

        #右选左旋 
        def rotate_right_left(self,p,c):
                g = c.lchild
                #s3 是g的右孩子
                s3 = g.rchild
                #s3绑到c的左孩子上   
                c.lchild = s3
                #反着连回去就要判断是否为空 
                if s3:
                        s3.parent = c
                #下面c和g交互了
                #c 是g的右孩子 
                g.rchild = c
                #g 是c的父亲 
                c.parent = g

                #s2 是g的左孩子         
                s2 = g.lchild
                #现在p的右孩子 等于s2
                p.rchild = s2

                if s2:
                        s2.parent = p

                g.lchild = p
                p.parent = g

                #更新 bf  插入s3   大于0就是等于1 是往右偏移
                if g.bf > 0 :
                        p.bf = -1
                        c.bf = 0
                elif g.bf < 0 : #插入s2 左边
                        p.bf = 0
                        c.bf = 1

                else:  #特殊情况,G插入进去来 刚插入进来的是叶子根节点, 所以等于0   G =0 
                        p.bf = 0
                        c.bf = 0
                #旋转之后的根
                return g

        #先左旋后右选 
        def rotate_left_right(self,p,c):
                g = c.rchild

                s2 = g.lchild
                c.rchild = s2

                if s2:
                        s2.parent = c

                g.lchild = c
                c.parent = g

                s3 = g.rchild
                p.lchild = s3

                if s3:
                        s3.parent = p

                g.rchild = p
                p.parent = g

                #更新 
                if g.bf < 0:
                        p.bf = 1
                        c.bf = 0
                elif g.bf > 0:
                        p.bf = 0
                        c.bf = -1

                else:
                        p.bf = 0
                        c.bf = 0

        #代码从左往右读 
        def insert_no_rec(self,val):
                #如果传递或者插入 有一个节点。balance变成0,停止了       
                #如果变成2或者-2 就不平衡了 
                # 1. 和BST一样,插入
                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的位置上
                                        p.lchild = AVLNode(val)
                                        #孩子指向了父亲 
                                        p.lchild.parent = p
                                        #保存这个元素插入的位置 
                                        node = p.lchild # node 存储的就是插入的节点
                                        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:   # val == p.data  同样的元素不能多次插入 
                                return

                #右沉左旋,左沉右选             
                #更新balance factor  从它的父亲网上更新
                while node.parent:  # node.parent不空  保证node的从父亲开始
                        #左孩子-1  右孩子+1
                        if node.parent.lchild == node: # 传递是从左子树来的,左子树更沉了 插入的
                        #更新node.parent的bf -= 11  这是父亲
                                if node.parent.bf < 0: # 原来node.parent.bf == -1, 更新后变成-2
                                        # 做旋转
                                        # 看node哪边沉
                                        x = node.parent  # 旋转前的子树的根
                                        #右沉 这是子
                                        if node.bf > 0:
                                                #旋转之后的新的根
                                                n = self.rotate_left_right(node.parent, node)
                                        else:
                                                n = self.rotate_right_left(node.parent, node)
                                        # 记得:把n和g连起来
                                elif node.parent.bf > 0: # 原来node.parent.bf = 1,更新之后变成0
                                        #更新之后减1 变成零   等于0就不再传递了
                                        node.parent.bf = 0
                                        break
                                else: # 原来node.parent.bf = 0,更新之后变成-1  
                                        node.parent.bf = -1
                                        #网上继续走 继续看
                                        node = node.parent
                                        continue
                        else: # 传递是从右子树来的,右子树更沉了 插入
                                #更新node.parent.bf += 1
                                #这是父亲
                                if node.parent.bf > 0:  # 原来node.parent.bf == 1, 更新后变成2
                                        # 做旋转
                                        # 看node哪边沉
                                        g = node.parent.parent # 为了连接旋转之后的子树
                                        x = node.parent  # 旋转前的子树的根
                                        #这是子
                                        if node.bf < 0: # node.bf = 1
                                                 #旋转之后的新的根
                                                n = self.rotate_right_left(node.parent, node)
                                        else:   # node.bf = -1
                                                n = self.rotate_left(node.parent, node)
                                        # 记得连起来
                                elif node.parent.bf < 0: # 原来node.parent.bf = -1,更新之后变成0
                                        node.parent.bf = 0
                                        break
                                else: # 原来node.parent.bf = 0,更新之后变成1
                                        node.parent.bf = 1
                                        node = node.parent
                                        continue

                        # 链接旋转后的子树
                        n.parent = g
                        if g: # g不是空
                                if x == g.lchild:
                                        g.lchild = n
                                else:
                                        g.rchild = n
                                break
                        else:
                                self.root = n
                                break



tree = AVLTree([9,8,7,6,5,4,3,2,1])
tree.pre_order(tree.root)
print("")
tree.in_order(tree.root)

二叉搜索树

import random

class BiTreeNode:
    def __init__(self, data):
        self.data = data
        self.lchild = None   # 左孩子
        self.rchild = None  # 右孩子
        self.parent = None

class BST:
    def __init__(self, li=None):
        self.root = None
        if li:
            for val in li:
                self.insert_no_rec(val)

    def insert(self, node, val):
        if not node:
            node = BiTreeNode(val)
        elif val < node.data:
            node.lchild = self.insert(node.lchild, val)
            node.lchild.parent = node
        elif val > node.data:
            node.rchild = self.insert(node.rchild, val)
            node.rchild.parent = node
        return node

    def insert_no_rec(self, val):
        p = self.root
        if not p:               # 空树
            self.root = BiTreeNode(val)
            return
        while True:
            if val < p.data:
                if p.lchild:
                    p = p.lchild
                else:           # 左孩子不存在
                    p.lchild = BiTreeNode(val)
                    p.lchild.parent = p
                    return
            elif val > p.data:
                if p.rchild:
                    p = p.rchild
                else:
                    p.rchild = BiTreeNode(val)
                    p.rchild.parent = p
                    return
            else:
                return

    def query(self, node, val):
        if not node:
            return None
        if node.data < val:
            return self.query(node.rchild, val)
        elif node.data > val:
            return self.query(node.lchild, val)
        else:
            return node

    def query_no_rec(self, val):
        p = self.root
        while p:
            if p.data < val:
                p = p.rchild
            elif p.data > val:
                p = p.lchild
            else:
                return p
        return None

    def pre_order(self, root):
        if root:
            print(root.data, 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, end=',')
            self.in_order(root.rchild)

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


    def __remove_node_1(self, node):
        # 情况1:node是叶子节点
        if not node.parent:
            self.root = None
        if node == node.parent.lchild:  #node是它父亲的左孩子
            node.parent.lchild = None
        else:   #右孩子
            node.parent.rchild = None

    def __remove_node_21(self, node):
        # 情况2.1:node只有一个左孩子
        if not node.parent: # 根节点
            self.root = node.lchild
            node.lchild.parent = None
        elif node == node.parent.lchild:
            node.parent.lchild = node.lchild
            node.lchild.parent = node.parent
        else:
            node.parent.rchild = node.lchild
            node.lchild.parent = node.parent

    def __remove_node_22(self, node):
        # 情况2.2:node只有一个右孩子
        if not node.parent:
            self.root = node.rchild
        elif node == node.parent.lchild:
            node.parent.lchild = node.rchild
            node.rchild.parent = node.parent
        else:
            node.parent.rchild = node.rchild
            node.rchild.parent = node.parent


    def delete(self, val):
        if self.root:   # 不是空树
            node = self.query_no_rec(val)
            if not node: # 不存在
                return False
            if not node.lchild and not node.rchild: #1. 叶子节点
                self.__remove_node_1(node)
            elif not node.rchild:       # 2.1 只有一个左孩子
                self.__remove_node_21(node)
            elif not node.lchild:       # 2.2 只有一个右孩子
                self.__remove_node_22(node)
            else:   # 3. 两个孩子都有
                min_node = node.rchild
                while min_node.lchild:
                    min_node = min_node.lchild
                node.data = min_node.data
                # 删除min_node
                if min_node.rchild:
                    self.__remove_node_22(min_node)
                else:
                    self.__remove_node_1(min_node)




#
#

tree = BST([1,4,2,5,3,8,6,9,7])
tree.pre_order(tree.root)
print("")
tree.in_order(tree.root)
print("")
tree.post_order(tree.root)
print("")

#
# tree.delete(4)
# tree.delete(1)
# tree.delete(8)
# tree.in_order(tree.root)

在这里插入图片描述