python平衡二叉排序树

这篇博客介绍了AVL树(自平衡二叉查找树)的实现,包括节点类、AVLNode类和DictAVL类。详细展示了插入、旋转调整等操作,以保持树的平衡。同时,还提到了二叉排序树的搜索、插入和删除等基本操作。此外,还提及了Assoc类用于存储键值对,并提供了顺序栈SStack类的实现。
摘要由CSDN通过智能技术生成

话不多说,兄弟萌,show me the code!

from chapter8.btSearch import DictBinTree
from chapter8.Assoc import Assoc

class BinTNode:
    """树节点类"""
    def __init__(self,dat,left=None,right=None):
        self.data = dat
        self.left = left
        self.right = right

class AVLNode(BinTNode):
    def __init__(self,data):
        BinTNode.__init__(self,data)
        self.bf = 0

class DictAVL(DictBinTree):
    def __init__(self):
        DictBinTree.__init__(self)

    @staticmethod
    def LL(a,b):
        a.left = b.right
        b.right = a
        a.bf = b.bf = 0
        return b

    @staticmethod
    def RR(a,b):
        a.right = b.left
        b.left = a
        a.bf = b.bf = 0
        return b

    @staticmethod
    def LR(a,b):
        c = b.right
        a.left, b.right = c.right, c.left
        c.left, c.right = b, a
        if c.bf == 0:
            """c本身就是插入节点"""
            a.bf = b.bf = 0
        elif c.bf == 1:
            """新节点在c的左子树"""
            a.bf = -1
            b.bf = 0
        else:
            """新节点在c的右子树"""
            a.bf = 0
            b.bf = 1
        c.bf = 0
        return c

    @staticmethod
    def RL(a,b):
        c = b.left
        a.right, b.left = c.left, c.right
        c.left, c.right = a, b
        if c.bf == 0:
            """c本身就是插入节点"""
            a.bf = 0
            b.bf = 0
        elif c.bf == 1:
            """新节点在c的左子树"""
            a.bf = 0
            b.bf = -1
        else:
            """新节点在c的右子树"""
            a.bf = 1
            b.bf = 0
        c.bf = 0
        return c

    def insert(self,key,value):
        a = p = self._root
        if a == None:
            self._root = AVLNode(Assoc(key,value))
            return
        pa = q = None # 维持pa,q为a,p的父节点
        while p is not None:
            """确定插入位置及最小非平衡子树"""
            if key == p.data.key:
                """key存在,修改关联值并结束"""
                p.data.value = value
                return
            if p.bf != 0:
                pa, a = q, p # 已知最小非平衡子树
            q = p
            if key < p.data.key:
                p = p.left
            else:
                p = p.right
        # q是插入点的父节点, pa, a 记录最小非平衡子树
        node = AVLNode(Assoc(key,value))
        if key < q.data.key:
            q.left = node # 作为左子节点
        else:
            q.right = node # 或右子节点
        # 新节点已插入,a 是最小不平衡子树
        if key < a.data.key:
            """新节点在a的左子树"""
            p = b = a.left
            d = 1
        else:
            """新节点在a的右子树"""
            p = b = a.right
            d = -1 # d记录新节点在a的哪棵子树
        # 修改b到新节点路径上各节点的BF值,b为a的子节点
        while p != node:
            """node一定存在,不用判断p空"""
            if key < p.data.key:
                """p的左子树增高"""
                p.bf = 1
                p = p.left
            else:
                """p的右子树增高"""
                p.bf = -1
                p = p.right
        if a.bf == 0:
            """a的原bf为0,不会失衡"""
            a.bf = 0
            return
        if a.bf == -d:
            """新节点在较低子树里"""
            a.bf = 0
            return
        # 新节点在较高子树,失衡,必须调整
        if d == 1:
            if b.bf == 1:
                b = DictAVL.LL(a,b) # LL调整
            else:
                b = DictAVL.LR(a,b) # LR调整
        else:
            if b.bf == -1:
                b = DictAVL.RR(a,b) # RR调整
            else:
                b = DictAVL.RL(a,b) # RL调整

        if pa == None:
            """原a为树根,修改root"""
            self._root = b
        else:
            """a非树根,新树接在正确位置"""
            if pa.left == a:
                pa.left = b
            else:
                pa.right = b

 

DictBinTree类:
from chapter8.Assoc import Assoc
from stack_queue.code import SStack

def btSearch(btree,key):
    """二叉排序树的检索算法"""
    bt = btree
    while bt != None:
        entry = bt.data
        if key < entry.key:
            bt = bt.left
        elif key > entry.key:
            bt = bt.right
        else: # key == entry.key
            return entry.value # 返回关键码的关联值
    # 走完整棵树仍没有找到
    return None

class BinTNode:
    """树节点类"""
    def __init__(self,dat,left=None,right=None):
        self.data = dat
        self.left = left
        self.right = right

class DictBinTree:
    """字典二叉排序树类"""
    def __init__(self):
        self._root = None

    def isEmpty(self):
        """判断是否为空"""
        return self._root is None

    def search(self,key):
        """检索"""
        bt = self._root
        while bt != None:
            entry = bt.data
            if key < entry.key:
                bt = bt.left
            elif key > entry.key:
                bt = bt.right
            else:  # key == entry.key
                return entry.value  # 返回关键码的关联值
        # 走完整棵树仍没有找到
        return None

    def insert(self,key,value):
        bt = self._root
        if bt == None:
            """如果树为空,直接建立一个新关键码和关联值的树根节点"""
            self._root = BinTNode(Assoc(key,value))
            return
        """否则搜索新节点的插入位置,沿子节点关系向下"""
        while True:
            entry = bt.data
            if key < entry.key:
                """遇到应该走左子树"""
                if bt.left == None:
                    """而左子树为空"""
                    bt.left = BinTNode(Assoc(key,value))
                    return
                bt = bt.left
            elif key > entry.key:
                """遇到应该走右子树"""
                if bt.right == None:
                    """而右子树为空"""
                    bt.right = BinTNode(Assoc(key,value))
                    return
                return bt.right
            else:
                """碰到值相等"""
                bt.data.value = value
                return

    def values(self):
        """中序遍历,值生成迭代器"""
        t,s = self._root,SStack()
        while t != None or not s.is_empty():
            while t != None:
                s.push(t)
                t = t.left
            t = s.pop()
            yield t.data.key, t.data.value
            t = t.right

    def delete(self,key):
        """删除节点,保证树的结构不变"""
        p,q = None, self._root # 维持p为q的父节点 ,从树根开始找q
        while q != None and q.data.key != key:
            p = q # 维持p为q的父节点
            if key < q.data.key:
                q = q.left
            else:
                q = q.right
            if q is None:
                return # 树中没有关键码key

            """到这里q引用要删除节点,p是其父节点或None(这时q是根节点)"""
            if q.left == None:
                """q没有左子节点"""
                if p == None:
                    """q是根节点,直接修改root"""
                    self._root = q.right
                elif q == p.left:
                    p.left = q.right
                else:
                    p.right = q.right
                return

            r = q.left
            while r.right != None:
                r = r.right
            r.right = q.right
            if p == None:
                """q是根节点,修改_root"""
                self._root = q.left
            elif p.left == q:
                p.left = q.left
            else:
                p.right =q.left

    def print(self):
        for k,v in self.entries():
            print(k,v)


def buildDictBinTree(entries):
    dic = DictBinTree()
    for k,v in entries:
        dic.insert(k,v)
    return dic


class DictOptBinTree(DictBinTree):
    def __init__(self,seq):
        DictBinTree.__init__(self)
        data = sorted(seq)
        self._root = DictOptBinTree.buildOBT(data,0,len(data)-1)

    @staticmethod
    def buildOBT(data,start,end):
        if start > end:
            return None
        mid = (end+start)//2
        left = DictOptBinTree.buildOBT(data,start,mid-1)
        right = DictOptBinTree.buildOBT(data,mid+1,end)
        return BinTNode(Assoc(*data[mid],left,right))

 

Assoc类:
class Assoc:
    def __init__(self,key,value):
        self.key = key
        self.value = value

    def __lt__(self, other):
        """有时有些操作需要考虑排序"""
        return self.key < other.key

    def __le__(self, other):
        return self.key < other.key or self.key == other.key

    def __str__(self):
        """定义字符串表示形式便于输出和交互"""
        return f"Assoc({self.key},{self.value})"
SStack类:
"""栈的顺序表实现"""

class StackUnderflow(ValueError): # 栈下溢(空栈访问)
    pass

class SStack(): # 基于顺序表技术实现的栈类
    def __init__(self): # 用list对象 _elems存储栈中元素
        self._elems = [] # 所有栈操作都映射到list操作

    def is_empty(self):
        return self._elems == []

    def top(self): # 查看栈顶元素
        if self._elems == []:
            raise StackUnderflow("in SStack.top()")

        return self._elems[-1]

    def push(self,elem):
        self._elems.append(elem)

    def pop(self): # 弹出栈顶元素
        if self._elems == []:
            raise StackUnderflow("in SStack.pop()")

        return self._elems.pop()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值