数据结构之二叉搜索树与AVL树

二叉搜索树

若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉排序树

在这里插入图片描述

平衡二叉搜索树

平衡二叉搜索树:又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
在这里插入图片描述

代码


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为空
            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 pre_order(self,root):
        if root:  # 递归终止条件
            print(root.data, end=',')
            self.pre_order(root.lchild)
            self.pre_order(root.rchild)

    #查找
    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

    #删除
    # 情况一:node是叶子结点
    def __remove_node_1(self,node):
        if not node.parent:    # node.parent为空,只有根的父节点为空,即当前节点为根节点的时候,进行以下操作
            self.root=None

        if node ==node.parent.lchild:    #node是父节点的左孩子
            node.parent.lchild=None
        else:
            node.parent.rchild=None

    #情况二:node只有一个左孩子
    def __remove_node_21(self,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

    #情况三:node只有一个右节点
    def __remove_node_22(self,node):
        if not node.parent:
            self.root=node.rchild
            node.rchild.parent=None

        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.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:       #如果有右节点(min_node肯定没有叶子结点)
                    self.__remove_node_22(min_node)
                else:
                    self.__remove_node_1(min_node)


    def query_no_rec(self,val):   #不使用递归
        p=self.root
        while p:
            if p.data<val:
                p=p.rchild
            if p.data>val:
                p=p.lchild
            else:
                return p
        return None

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 ratate_left(self,p,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 ratate_right(self,p,c):  #右旋
        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 ratate_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:
            p.bf=-1
            c.bf=0
        elif g.bf<0:
            p.bf=0
            c.bf=1
        else:  #插入的是g
            p.bf=0
            c.bf=0

    def ratate_left_right(self,p,c) :
        g=c.lchild

        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

        #更新bf
        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):
        #1.和BST一样,插入
        p=self.root
        if not p:   #空树
            self.root=AVLNode(val)
            return
        while True:
            if val<p.data:
                if p.child:
                    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

        #2.更新balance factor
        while node.parent:     #node.parent不空
            if node.parent.lchild==node: #传递是从左子树来的,左子树更沉了
                #更新node.parent的bf-=1
                if node.parent.bf<0: #原来的node.bf=-1,更新后变成-2
                    #做旋转
                    #看哪边更沉
                    g=node.parent.parent   #为了连接旋转之后的子树
                    x = node.parent  # 旋转前子树的根
                    if node.bf>0:       #先左旋后右旋
                        n=self.ratate_left_right(node.parent,node)
                    else:
                        n=self.ratate_right(node.parent,node)

                    #记得:把n和g连接起来

                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



            else:     #传递是从右边来的,右子树更沉了
                #更新后的node.parent.bf+=1
                if node.parent.bf>0:    #原来node.parent.bf=1,更新后变成2
                    #做旋转
                    # 看哪边更沉
                    g = node.parent.parent  # 为了连接旋转之后的子树
                    x=node.parent     #旋转前子树的根
                    if node.bf < 0:  # node.bf=1
                        n = self.ratate_right_left(node.parent, node)
                    else:
                        n = self.ratate_left(node.parent, node)

                    # 记得:把n和g连接起来

                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([1,2,3,4,5,6,7,8,9])

tree.pre_order(tree.root)
print()
tree.pre_order(tree.root)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值