话不多说,兄弟萌,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()