目录:
1.扩展buildParseTree方法,使其能够处理字符间没有空格的数字表达式。
2.修改buildParseTree和evaluate,使它们支持逻辑运算符(and、or、not)。注意,not是一元运算符,这会让代码有点复杂。
3.使用findSuccessor方法,写一个非递归的二叉搜索树中序遍历方法。
4.修改二叉搜索树的实现代码,从而实现线索二叉搜索树。为线索二叉搜索树写一个非递归的中序遍历方法。线索二叉搜索树为其中的每个节点都维护者指向后继节点的引用。
5.修改二叉搜索树的实现代码,以正确处理重复的键。也就是说,如果键已在树中,就替换有效载荷,而不是用同一个键插入一个新节点。
6.创建限定大小的二叉堆。也就是说,堆只保持n个最重要的元素。如果堆的大小超过了n,就会舍弃最不重要的元素。
7.整理printexp函数,去掉数字周围多余的括号。
8.使用buildHeap方法,针对列表写一个时间复杂度为O ( l o g n ) O(logn)O(logn)的排序函数。
9.写一个函数,以数学表达式解析树为参数,计算各变量的导数。
10.将二叉树实现为最大堆。
11.使用BinaryHeap类。实现一个叫做PriorityQueue的新类。为PriorityQueue类实现构造方法,以及enqueue方法和dequeue方法。
12.实现AVL树的delete方法。
1.扩展buildParseTree方法,使其能够处理字符间没有空格的数字表达式。
2.修改buildParseTree和evaluate,使它们支持逻辑运算符(and、or、not)。注意, not是一元运算符,这会让代码有点复杂。
"""1.扩展buildParseTree方法,使其能够处理字符间没有空格的数字表达式
2.修改buildParseTree和evaluate,使它们支持逻辑运算符(and、or、not)。注意,not是一元运算符"""
import operator # 操作符模块
# 自定义栈类
class Stack(object):
def __init__(self): # 初始化空栈
self.items = []
def isEmpty(self): # 是否为空
return self.items == []
def push(self, item): # 入栈
self.items.append(item)
def pop(self): # 出栈
return self.items.pop()
def peek(self): # 查看栈顶元素
return self.items[len(self.items)-1]
def size(self): # 查看栈的大小
return len(self.items)
# 自定义二叉树类
class BinaryTree(object):
# 初始化二叉树
def __init__(self, rootObj):
self.root = rootObj
self.leftChild = None
self.rightChild = None
# 插入左子树
def insertLeft(self, newNode):
if self.leftChild == None: # 若左子树为空,则
self.leftChild = BinaryTree(newNode) # 直接生成左子树
else:
t = BinaryTree(newNode) # 生成初始二叉树
t.leftChild = self.leftChild # 将原左子树赋值给新二叉树的左子树
self.leftChild = t # 再将新二叉树赋值给原二叉树的左子树
# 插入右子树
def insertRight(self, newNode):
if self.rightChild == None:
self.rightChild = BinaryTree(newNode)
else:
t = BinaryTree(newNode)
t.rightChild = self.rightChild
self.rightChild = t
# 获取右子树
def getRightChild(self):
return self.rightChild
# 获取左子树
def getLeftChild(self):
return self.leftChild
# 设置根节点值
def setRootVal(self, obj):
self.root = obj
# 获取根节点值
def getRootVal(self):
return self.root
# 解析树生成函数
def buildParseTree2(fpexp): # (传入的完全括号表达式)
fplist1 = fpexp.split() # 将传入的完全括号表达式以空格分割成list
fplist = [] #
for i in fplist1: # 遍历表达式
if i in ['and', 'not', 'or']: # 如果遍历到
fplist.append(i) # 添加到列表
elif i == '(not': # 如果遍历到'(not'
fplist.append('not') # 就只添加'not'
else:
for j in i:
if j == 'n':
fplist.append('not')
break
else:
fplist.append(j)
pStack = Stack() # 实例化栈类
eTree = BinaryTree('') # 实例化二叉树类,必须有''
pStack.push(eTree) # 将空二叉树的根节点(空)入栈
currentTree = eTree # 将空二叉树的根节点(空)作为当前节点
currentTree.setRootVal(eval(fpexp))
for i in fplist: # 循环处理表达式list元素
if i == '(': # 遇到"(",则
currentTree.insertLeft('') # 创建当前节点的空左子节点
pStack.push(currentTree) # 将当前节点入栈
currentTree = currentTree.getLeftChild() # 将该左子节点作为当前节点
elif i not in '+-*/)' and i not in ['and', 'or', 'not']: # 遇到操作数,则
currentTree.setRootVal(eval(i)) # 将操作数设为当前节点的根值
parent = pStack.pop() # 将出栈节点(父节点)作为当前节点
currentTree = parent
elif i in '+-*/': # 遇到操作符,则
currentTree.setRootVal(i) # 将操作符设为当前节点的根植
currentTree.insertRight('') # 创建当前节点的空右子节点
pStack.push(currentTree) # 将当前节点入栈
currentTree = currentTree.getRightChild() # 将该右子节点作为当前节点
elif i == ')': # 遇到")",则
currentTree = pStack.pop() # 将出栈节点(父节点)作为当前节点
elif i in ['and', 'or', 'not']: # 遇到逻辑运算符,则
currentTree.setRootVal(i) # 将操作符设为当前节点的根植
currentTree.insertRight('') # 创建当前节点的空右子节点
pStack.push(currentTree) # 将当前节点入栈
currentTree = currentTree.getRightChild() # 将该右子节点作为当前节点
else:
raise ValueError('Unknown Operator:' + i) # 抛出异常
return eTree
# 求值函数,parseTree为当前整个解析树的根节点
def evaluate(parseTree):
# opers字典是操作符与其对应的运算函数的集合
opers = {'+': operator.add, '-': operator.sub, '*': operator.mul,
'/': operator.truediv, 'and': fn_and, 'or': fn_or,
'not': fn_not}
leftC = parseTree.getLeftChild() # 获取解析树根节点的左子树
rightC = parseTree.getRightChild() # 获取解析树根节点的右子树
if parseTree.getRootVal() == 'not': # 如果根节点的值==not
fn = opers[parseTree.getRootVal()] # 获取解析树根节点值对应的opers字典值作为运算函数
return fn(rightC) # 将递归获取的左右子树值运算后返回
else: # 若当前节点不存在左右子树,说明该节点是叶节点,则
if leftC and rightC:
fn = opers[parseTree.getRootVal()]
return fn(evaluate(leftC), evaluate(rightC))
else:
return parseTree.getRootVal()
def fn_and(left, right):
return left and right
def fn_or(left, right):
return left or right
def fn_not(right):
return not right
if __name__ == '__main__':
tree = buildParseTree2('((1+0) or (not 0))')
#tree = buildParseTree2(" ( ( ( 3 + 6 ) * ( 7 - 5 ) ) + 4 )")
print(evaluate(tree))
3.使用findSuccessor方法,写一个非递归的二叉搜索树中序遍历方法。
"""3.使用findSuccessor方法,写一个非递归的二叉搜索树中序遍历方法。"""
class BinarySearchTree:
def __init__(self):
self.root = None # 根节点为空
self.size = 0 # 节点长度为0
def length(self): # 返回长度
return self.size
def __len__(self): # 魔法方法返回长度
return self.size
def __iter__(self): # 实现for循环
return self.root.__iter__()
def put(self, key, val): # 主添加(键,值)
if self.root: # 不为空,有节点
self._put(key, val, self.root) # 调用辅助添加方法(键,值,指针)
else: # 反之
self.root = TreeNode(key, val) # 创建对象传入(键,值)
self.size = self.size + 1 # 节点长度+1
def _put(self, key, val, currentNode): # 副添加(键,值,指针)
if key < currentNode.key: # 如果传入的键小于当前节点的键
if currentNode.hasLeftChild(): # 当前节点有左子
self._put(key, val, currentNode.leftChild) # 递归调用左子去办
else: # 没左子
# 直接创建一个左子节点赋值给当前左子
currentNode.leftChild = TreeNode(key, val, parent=currentNode)
else: # 传入的键大于当前节点的键
if currentNode.hasRightChild(): # 当前节点有右子
self._put(key, val, currentNode.rightChild) # 递归调用右子去办
else: # 没右子
# 直接创建一个右子节点赋值给当前右子
currentNode.rightChild = TreeNode(key, val, parent=currentNode)
def __setitem__(self, key, value): # 像字典一样输入
self.put(key, value)
def get(self, key): # 主查找
if self.root: # 不为空,有节点
res = self._get(key, self.root) # 调用副查找
if res: # 如果找到了
return res.payload # 返回value
else: # 反之没找到
return None
else: # 反之为空
return None
def _get(self, key, currentNode): # 副查找
if not currentNode: # 如果节点为空
return None
elif currentNode.key == key:
return currentNode
elif key < currentNode.key:
return self._get(key, currentNode.leftChild)
else:
return self._get(key, currentNode.rightChild)
def __getitem__(self, key): # 像字典一样查找
return self.get(key)
def __contains__(self, key): # 检查树中是否有某个键(in方法)
if self._get(key, self.root):
return True
else:
return False
# 主删除
def delete(self, key): # 主删除(键)
if self.size > 1: # 节点长度>1
nodeToRemove = self._get(key, self.root) # 调用查找方法找到你要删除的键
if nodeToRemove: # 如果找到了
self.remove(nodeToRemove) # 调用删除副方法
self.size = self.size - 1 # 节点长度-1
else: # 没找到了
raise KeyError('错误,键不在树中')
# 节点长度==1就只有根节点了==你要找的
elif self.size == 1 and self.root.key == key:
self.root = None # 把根节点设为空
self.size = self.size - 1 # 节点长度-1
else:
raise KeyError('错误,键不在树中')
def remove(self, currentNode): # 副删除
# 情况1.删除节点没有子节点
if currentNode.isLeaf(): # 如果是叶子节点
if currentNode == currentNode.parent.leftChild: # 如果是父节点的左子
currentNode.parent.leftChild = None # 就父节点的左子设为空
else:
currentNode.parent.rightChild = None # 就父节点的右子设为空
# 情况3.有二个节点
elif currentNode.hasBothChildren(): # 当前节点有两子
succ = currentNode.findSuccessor() # 调用寻找后继节点
succ.spliceOut() # 调用删除后继节点
currentNode.key = succ.key # 当前节点的键等于后继节点的键
currentNode.payload = succ.payload # 当前节点的值等于后继节点的值
# 情况2.有一个节点
else:
if currentNode.hasLeftChild(): # 当前节点有左子
if currentNode.isLeftChild(): # 他自己是左子
currentNode.leftChild.parent = currentNode.parent
currentNode.parent.leftChild = currentNode.leftChild
elif currentNode.isRightChild(): # 他自己是右子
currentNode.leftChild.parent = currentNode.parent
currentNode.parent.rightChild = currentNode.leftChild
else: # 他自己是根节点
currentNode.replaceNodeData(currentNode.leftChild.key,
currentNode.leftChild.payload,
currentNode.leftChild.leftChild,
currentNode.leftChild.rightChild
)
else: # 当前反之节点有右子
if currentNode.isLeftChild(): # 他自己是左子
currentNode.rightChild.parent = currentNode.parent
currentNode.parent.leftChild = currentNode.rightChild
elif currentNode.isRightChild(): # 他自己是右子
currentNode.rightChild.parent = currentNode.parent
currentNode.parent.rightChild = currentNode.rightChild
else: # 他自己是根节点
currentNode.replaceNodeData(currentNode.rightChild.key,
currentNode.rightChild.payload,
currentNode.rightChild.leftChild,
currentNode.rightChild.rightChild
)
def inorder(self): # 非递归中序遍历
currentNode = self.root
while currentNode:
beginNode = currentNode
currentNode = currentNode.leftChild
while beginNode.findSuccessor():
print(beginNode.key)
beginNode = beginNode.findSuccessor()
print(beginNode.key)
class TreeNode:
def __init__(self, key, val, left=None, right=None, parent=None, succ=None, balanceFactor=0):
self.key = key # 键
self.payload = val # 值
self.leftChild = left # 左子
self.rightChild = right # 右子
self.parent = parent # 指针
self.succ = succ
self.balanceFactor = balanceFactor # 平衡因子
def height(self): # 树高
height_l = 0
height_r = 0
if self.isLeaf():
return 0
if self.leftChild:
height_l = self.leftChild.height()
if self.rightChild:
height_r = self.rightChild.height()
return max(height_l, height_r) + 1
def hasLeftChild(self): # 是否有左子(none就是没有)
return self.leftChild
def hasRightChild(self): # 是否有右子
return self.rightChild
def hasAnyChildren(self): # 是否有孩子
return self.rightChild or self.leftChild
def hasBothChildren(self): # 是否有两孩子
return self.rightChild and self.leftChild
def isLeftChild(self): # 是不是父节点左子
return self.parent and self.parent.leftChild == self
def isRightChild(self): # 是不是父节点右子
return self.parent and self.parent.rightChild == self
def isRoot(self): # 是不是根节点
return not self.parent
def isLeaf(self): # 是不是叶子节点
return not (self.rightChild or self.leftChild)
def hasAnyChildren(self): # 是否有孩子
return self.rightChild or self.leftChild
def replaceNodeData(self, key, value, lc, rc): # 替换(键,值左子,右子)
self.key = key # 键
self.payload = value # 值
self.leftChild = lc # 左子
self.rightChild = rc # 右子
if self.hasLeftChild(): # 如果有左子
self.leftChild.parent = self # 左子的指针就指向我自己
if self.hasRightChild(): # 如果有右子
self.rightChild.parent = self # 右子的指针就指向我自己
def findSuccessor(self): # 寻找后继节点
succ = None # 后继节点先为空
if self.hasRightChild(): # 如果有右子
succ = self.rightChild.findMin() # 找右子树里最小的
else: # 反之没有右子
if self.parent: # 如果有父节点
if self.isLeftChild(): # 如果自己是左子
succ = self.parent # 后继节点是他的父节点
else: # 自己是右子
self.parent.rightChild = None # 先把自己设为空(不设为空就会查到自己)
succ = self.parent.findSuccessor() # 递归调用找后继
self.parent.rightChild = self # 父节点的右子是自己
return succ # 返回后继节点
def findMin(self): # 找最小节点
current = self # 把当前节点赋值给变量(指针)
while current.hasLeftChild(): # 如果当前节点有左子就循环
current = current.leftChild # 当前指针就指向左子
return current # 返回最小节点
def spliceOut(self): # 删除后继节点
if self.isLeaf(): # 如果没子节点
if self.isLeftChild(): # 如果自己是左子
self.parent.leftChild = None # 把他父亲的左子变成空
else: # 反之自己是右子
self.parent.rightChild = None # 把他父亲的右子变成空
elif self.hasAnyChildren(): # 如果有子节点
if self.hasLeftChild(): # 他有左子
if self.isLeftChild(): # 他自己也是左子
self.parent.leftChild = self.leftChild # 让他的儿子对爷爷叫爸爸
else: # 他自己是右子
self.parent.rightChild = self.leftChild # 他父亲的右子等于他的左子
self.leftChild.parent = self.parent # 他左子的父亲等于他的父亲
else: # 他有右子
if self.isLeftChild(): # 他自己也是左子
self.parent.leftChild = self.rightChild # 他父亲的左子等于他的右子
else: # 他自己是右子
self.parent.rightChild = self.rightChild # 他父亲的右子等于他的右子
self.rightChild.parent = self.parent # 他右子的父亲等于他的父亲
def __iter__(self): # 二叉搜索树迭代器
if self: # 当前节点不为空
if self.hasLeftChild(): # 当前节点有左子
for elem in self.leftChild: # 遍历左子
yield elem # 生成数据
yield self.key #
if self.hasRightChild(): # 当前节点有右子
for elem in self.rightChild: # 遍历右子
yield elem # 生成数据
if __name__ == '__main__':
tree = BinarySearchTree()
tree[1] = 'a'
tree[2] = 'b'
tree[3] = 'c'
tree[4] = 'd'
tree[5] = 'e'
tree[6] = 'f'
tree[7] = 'g'
tree[8] = 'h'
tree[9] = 'i'
tree[10] = 'j'
tree.inorder() # 中序遍历
4.修改二叉搜索树的实现代码,从而实现线索二叉搜索树。为二叉搜索树写一个非递归 的中序遍历方法。线索二叉搜索树为其中的每个节点都维护者指向后继节点的引用。
"""4.修改二叉搜索树的实现代码,从而实现线索二叉搜索树
。为线索二叉搜索树写一个非递归的中序遍历方法。
线索二叉搜索树为其中的每个节点都维护者指向后继节点的引用。"""
class BinarySearchTree: # 树类
def __init__(self):
self.root = None # 根节点为空
self.size = 0 # 节点长度为0
def length(self): # 返回长度
return self.size
def __len__(self): # 魔法方法返回长度
return self.size
def __iter__(self): # 实现for循环
return self.root.__iter__()
def height(self): # 树高
return self.root.height()
# 插入新节点
def put(self, key, val): # 主添加(键,值)
if self.root: # 不为空,有节点
self._put(key, val, self.root) # 调用辅助添加方法(键,值,指针)
else: # 反之
self.root = TreeNode(key, val) # 创建对象传入(键,值)
self.size = self.size + 1 # 节点长度+1
def _put(self, key, val, currentNode): # 副添加(键,值,指针)
if key < currentNode.key: # 如果传入的键小于当前节点的键
if currentNode.hasLeftChild(): # 当前节点有左子
self._put(key, val, currentNode.leftChild) # 递归调用左子去办
else: # 没左子
# 直接创建一个左子节点赋值给当前左子
currentNode.leftChild = TreeNode(key, val, parent=currentNode)
elif key == currentNode.key: # 练习5 处理重复的键
currentNode.payload = val
self.size = self.size + 1
else: # 传入的键大于当前节点的键
if currentNode.hasRightChild(): # 当前节点有右子
self._put(key, val, currentNode.rightChild) # 递归调用右子去办
else: # 没右子
# 直接创建一个右子节点赋值给当前右子
currentNode.rightChild = TreeNode(key, val, parent=currentNode)
def __setitem__(self, key, value): # 像字典一样输入
self.put(key, value)
# 查找键对应的值
def get(self, key): # 主查找
if self.root: # 不为空,有节点
res = self._get(key, self.root) # 调用副查找
if res: # 如果找到了
return res.payload # 返回value
else: # 反之没找到
return None
else: # 反之为空
return None
def _put(self, key, value, currentNode): # 副查找(键,值,指针)
if key < currentNode.key: # 如果查找的键小于当前节点的键
if currentNode.hasLeftChild(): # 如果当前节点有左子
self._put(key, value, currentNode.leftChild) # 递归调用左子去找
else: # 没有左子
currentNode.leftChild = TreeNode( # 他自己是根节点
key, value, parent=currentNode)
currentNode.leftChild.succ = currentNode # 当前节点左子的后继节点是当前节点
if currentNode.parent: # 如果当前节点有父亲
beginNode = currentNode.parent # 当前节点的父亲赋值给变量
while beginNode: # 无限循环
if beginNode.findSuccessor() == currentNode.leftChild: # 如果父节点的后继是当前节点的左子
beginNode.succ = currentNode.leftChild # 当前节点的左子赋值给父节点的后继
beginNode = beginNode.parent #
elif key == currentNode.key: # 如果查找的键是当前节点的键
currentNode.payload = value # 把值赋值给当前节点的值
else: # 反之查找的键大于当前节点的键
if currentNode.hasRightChild():# 如果当前节点有右子
self._put(key, value, currentNode.rightChild) # 递归调用右子去找
else:# 没有右子
currentNode.rightChild = TreeNode( # 他自己是根节点
key, value, parent=currentNode)
currentNode.succ = currentNode.rightChild # 当前节点的后继节点是当前节点的右子
if currentNode.rightChild.findSuccessor():
currentNode.rightChild.succ = currentNode.rightChild.findSuccessor()
def __getitem__(self, key): # 像字典一样查找
return self.get(key)
# 检查树中是否有某个键(in方法)
def __contains__(self, key):
if self._get(key, self.root):
return True
else:
return False
# 删除
def delete(self, key): # 主删除(键)
if self.size > 1: # 节点长度>1
nodeToRemove = self._get(key, self.root) # 调用查找方法找到你要删除的键
if nodeToRemove: # 如果找到了
self.remove(nodeToRemove) # 调用删除副方法
self.size = self.size - 1 # 节点长度-1
else: # 没找到了
raise KeyError('错误,键不在树中')
# 节点长度==1就只有根节点了==你要找的
elif self.size == 1 and self.root.key == key:
self.root = None # 把根节点设为空
self.size = self.size - 1 # 节点长度-1
else:
raise KeyError('错误,键不在树中')
def remove(self, currentNode): # 副删除
# 情况1.删除节点没有子节点
if currentNode.isLeaf(): # 如果是叶子节点
if currentNode == currentNode.parent.leftChild: # 如果是父节点的左子
currentNode.parent.leftChild = None # 就父节点的左子设为空
else:
currentNode.parent.rightChild = None # 就父节点的右子设为空
# 情况3.有二个节点
elif currentNode.hasBothChildren(): # 当前节点有两子
succ = currentNode.findSuccessor() # 调用寻找后继节点
succ.spliceOut() # 调用删除后继节点
currentNode.key = succ.key # 当前节点的键等于后继节点的键
currentNode.payload = succ.payload # 当前节点的值等于后继节点的值
# 情况2.有一个节点
else:
if currentNode.hasLeftChild(): # 当前节点有左子
if currentNode.isLeftChild(): # 他自己是左子
currentNode.leftChild.parent = currentNode.parent
currentNode.parent.leftChild = currentNode.leftChild
elif currentNode.isRightChild(): # 他自己是右子
currentNode.leftChild.parent = currentNode.parent
currentNode.parent.rightChild = currentNode.leftChild
else: # 他自己是根节点
currentNode.replaceNodeData(currentNode.leftChild.key,
currentNode.leftChild.payload,
currentNode.leftChild.leftChild,
currentNode.leftChild.rightChild
)
else: # 当前反之节点有右子
if currentNode.isLeftChild(): # 他自己是左子
currentNode.rightChild.parent = currentNode.parent
currentNode.parent.leftChild = currentNode.rightChild
elif currentNode.isRightChild(): # 他自己是右子
currentNode.rightChild.parent = currentNode.parent
currentNode.parent.rightChild = currentNode.rightChild
else: # 他自己是根节点
currentNode.replaceNodeData(currentNode.rightChild.key,
currentNode.rightChild.payload,
currentNode.rightChild.leftChild,
currentNode.rightChild.rightChild
)
def __delitem__(self, key): # 删除(键)
self.delete(key)
def inorder(self): # 中序遍历
currentNode = self.root
while currentNode:
beginNode = currentNode
currentNode = currentNode.leftChild
while beginNode.findSuccessor():
print(beginNode.key)
beginNode = beginNode.findSuccessor()
print(beginNode.key)
def inorder2(self): # 遍历出后继节点
currentNode = self.root
while currentNode:
beginNode = currentNode
currentNode = currentNode.leftChild
while beginNode.succ:
print(beginNode.key,beginNode.succ)
beginNode = beginNode.succ
print(beginNode.key,beginNode.succ)
class TreeNode():
def __init__(self, key, val, left=None, right=None, succ=None, parent=None):
self.key = key # 键
self.payload = val # 值
self.leftChild = left # 左子
self.rightChild = right # 右子
self.succ = succ # 后继节点
self.parent = parent # 指针
self.balanceFactor = 0 # 平衡因子
def height(self): # 树高
height_l = 0
height_r = 0
if self.isLeaf():
return 0
if self.leftChild:
height_l = self.leftChild.height()
if self.rightChild:
height_r = self.rightChild.height()
return max(height_l, height_r) + 1
def hasLeftChild(self): # 是否有左子(none就是没有)
return self.leftChild
def hasRightChild(self): # 是否有右子
return self.rightChild
def hasAnyChildren(self): # 是否有孩子
return self.rightChild or self.leftChild
def hasBothChildren(self): # 是否有两孩子
return self.rightChild and self.leftChild
def isLeftChild(self): # 是不是父节点左子
return self.parent and self.parent.leftChild == self
def isRightChild(self): # 是不是父节点右子
return self.parent and self.parent.rightChild == self
def isRoot(self): # 是不是根节点
return not self.parent
def isLeaf(self): # 是不是叶子节点
return not (self.rightChild or self.leftChild)
def hasAnyChildren(self): # 是否有孩子
return self.rightChild or self.leftChild
def replaceNodeData(self, key, value, lc, rc): # 替换(键,值左子,右子)
self.key = key # 键
self.payload = value # 值
self.leftChild = lc # 左子
self.rightChild = rc # 右子
if self.hasLeftChild(): # 如果有左子
self.leftChild.parent = self # 左子的指针就指向我自己
if self.hasRightChild(): # 如果有右子
self.rightChild.parent = self # 右子的指针就指向我自己
def __iter__(self): # 二叉搜索树迭代器
if self: # 当前节点不为空
if self.hasLeftChild(): # 当前节点有左子
for elem in self.leftChild: # 遍历左子
yield elem # 生成数据
yield self.key #
if self.hasRightChild(): # 当前节点有右子
for elem in self.rightChild: # 遍历右子
yield elem # 生成数据
# 寻找后继结点
def findSuccessor(self):
succ = None # 后继节点先为空
if self.hasRightChild(): # 如果有右子
succ = self.rightChild.findMin() # 找右子树里最小的
else: # 反之没有右子
if self.parent: # 如果有父节点
if self.isLeftChild(): # 如果自己是左子
succ = self.parent # 后继节点是他的父节点
else: # 自己是右子
self.parent.rightChild = None # 先把自己设为空(不设为空就会查到自己)
succ = self.parent.findSuccessor() # 递归调用找后继
self.parent.rightChild = self # 父节点的右子是自己
return succ # 返回后继节点
def findMin(self): # 找最小节点
current = self # 把当前节点赋值给变量(指针)
while current.hasLeftChild(): # 如果当前节点有左子就循环
current = current.leftChild # 当前指针就指向左子
return current # 返回最小节点
def spliceOut(self): # 删除后继节点
if self.isLeaf(): # 如果没子节点
if self.isLeftChild(): # 如果自己是左子
self.parent.leftChild = None # 把他父亲的左子变成空
else: # 反之自己是右子
self.parent.rightChild = None # 把他父亲的右子变成空
elif self.hasAnyChildren(): # 如果有子节点
if self.hasLeftChild(): # 他有左子
if self.isLeftChild(): # 他自己也是左子
self.parent.leftChild = self.leftChild # 让他的儿子对爷爷叫爸爸
else: # 他自己是右子
self.parent.rightChild = self.leftChild # 他父亲的右子等于他的左子
self.leftChild.parent = self.parent # 他左子的父亲等于他的父亲
else: # 他有右子
if self.isLeftChild(): # 他自己也是左子
self.parent.leftChild = self.rightChild # 他父亲的左子等于他的右子
else: # 他自己是右子
self.parent.rightChild = self.rightChild # 他父亲的右子等于他的右子
self.rightChild.parent = self.parent # 他右子的父亲等于他的父亲
if __name__ == '__main__':
tree = BinarySearchTree()
tree[1] = 'a'
tree[2] = 'b'
tree[3] = 'c'
tree[4] = 'd'
tree[5] = 'e'
tree[6] = 'f'
tree[7] = 'g'
tree[8] = 'h'
tree[9] = 'i'
tree[10] = 'j'
tree.inorder2() # 打印后继
5.修改二叉搜索树的实现代码,以正确处理重复的键。也就是说,如果键已在树中,就 替换有效载荷,而不是用同一个键插入一个新节点。
"""5.修改二叉搜索树的实现代码,以正确处理重复的键。也就是说,
如果键已在树中,就替换有效载荷,而不是用同一个键插入一个新节点。"""
class BinarySearchTree: # 树类
def __init__(self):
self.root = None # 根节点为空
self.size = 0 # 节点长度为0
def length(self): # 返回长度
return self.size
def __len__(self): # 魔法方法返回长度
return self.size
def __iter__(self): # 实现for循环
return self.root.__iter__()
def height(self): # 树高
return self.root.height()
# 插入新节点
def put(self, key, val): # 主添加(键,值)
if self.root: # 不为空,有节点
self._put(key, val, self.root) # 调用辅助添加方法(键,值,指针)
else: # 反之
self.root = TreeNode(key, val) # 创建对象传入(键,值)
self.size = self.size + 1 # 节点长度+1
def _put(self, key, val, currentNode): # 副添加(键,值,指针)
if key < currentNode.key: # 如果传入的键小于当前节点的键
if currentNode.hasLeftChild(): # 当前节点有左子
self._put(key, val, currentNode.leftChild) # 递归调用左子去办
else: # 没左子
# 直接创建一个左子节点赋值给当前左子
currentNode.leftChild = TreeNode(key, val, parent=currentNode)
elif key == currentNode.key: # 练习5 处理重复的键
currentNode.payload = val
self.size -= 1 # 避免重复计算
else: # 传入的键大于当前节点的键
if currentNode.hasRightChild(): # 当前节点有右子
self._put(key, val, currentNode.rightChild) # 递归调用右子去办
else: # 没右子
# 直接创建一个右子节点赋值给当前右子
currentNode.rightChild = TreeNode(key, val, parent=currentNode)
def __setitem__(self, key, value): # 像字典一样输入
self.put(key, value)
# 查找键对应的值
def get(self, key): # 主查找
if self.root: # 不为空,有节点
res = self._get(key, self.root) # 调用副查找
if res: # 如果找到了
return res.payload # 返回value
else: # 反之没找到
return None
else: # 反之为空
return None
def _get(self, key, currentNode): # 副查找
if not currentNode: # 如果节点为空
return None
elif currentNode.key == key:
return currentNode
elif key < currentNode.key:
return self._get(key, currentNode.leftChild)
else:
return self._get(key, currentNode.rightChild)
def __getitem__(self, key): # 像字典一样查找
return self.get(key)
# 检查树中是否有某个键(in方法)
def __contains__(self, key):
if self._get(key, self.root):
return True
else:
return False
# 删除
def delete(self, key): # 主删除(键)
if self.size > 1: # 节点长度>1
nodeToRemove = self._get(key, self.root) # 调用查找方法找到你要删除的键
if nodeToRemove: # 如果找到了
self.remove(nodeToRemove) # 调用删除副方法
self.size = self.size - 1 # 节点长度-1
else: # 没找到了
raise KeyError('错误,键不在树中')
# 节点长度==1就只有根节点了==你要找的
elif self.size == 1 and self.root.key == key:
self.root = None # 把根节点设为空
self.size = self.size - 1 # 节点长度-1
else:
raise KeyError('错误,键不在树中')
def remove(self, currentNode): # 副删除
# 情况1.删除节点没有子节点
if currentNode.isLeaf(): # 如果是叶子节点
if currentNode == currentNode.parent.leftChild: # 如果是父节点的左子
currentNode.parent.leftChild = None # 就父节点的左子设为空
else:
currentNode.parent.rightChild = None # 就父节点的右子设为空
# 情况3.有二个节点
elif currentNode.hasBothChildren(): # 当前节点有两子
succ = currentNode.findSuccessor() # 调用寻找后继节点
succ.spliceOut() # 调用删除后继节点
currentNode.key = succ.key # 当前节点的键等于后继节点的键
currentNode.payload = succ.payload # 当前节点的值等于后继节点的值
# 情况2.有一个节点
else:
if currentNode.hasLeftChild(): # 当前节点有左子
if currentNode.isLeftChild(): # 他自己是左子
currentNode.leftChild.parent = currentNode.parent
currentNode.parent.leftChild = currentNode.leftChild
elif currentNode.isRightChild(): # 他自己是右子
currentNode.leftChild.parent = currentNode.parent
currentNode.parent.rightChild = currentNode.leftChild
else: # 他自己是根节点
currentNode.replaceNodeData(currentNode.leftChild.key,
currentNode.leftChild.payload,
currentNode.leftChild.leftChild,
currentNode.leftChild.rightChild
)
else: # 当前反之节点有右子
if currentNode.isLeftChild(): # 他自己是左子
currentNode.rightChild.parent = currentNode.parent
currentNode.parent.leftChild = currentNode.rightChild
elif currentNode.isRightChild(): # 他自己是右子
currentNode.rightChild.parent = currentNode.parent
currentNode.parent.rightChild = currentNode.rightChild
else: # 他自己是根节点
currentNode.replaceNodeData(currentNode.rightChild.key,
currentNode.rightChild.payload,
currentNode.rightChild.leftChild,
currentNode.rightChild.rightChild
)
def __delitem__(self, key): # 删除(键)
self.delete(key)
# 寻找后继结点
def findSuccessor(self):
succ = None # 后继节点先为空
if self.hasRightChild(): # 如果有右子
succ = self.rightChild.findMin() # 找右子树里最小的
else: # 反之没有右子
if self.parent: # 如果有父节点
if self.isLeftChild(): # 如果自己是左子
succ = self.parent# 后继节点是他的父节点
else:# 自己是右子
self.parent.rightChild = None # 先把自己设为空(不设为空就会查到自己)
succ = self.parent.findSuccessor() # 递归调用找后继
self.parent.rightChild = self # 父节点的右子是自己
return succ # 返回后继节点
def findMin(self): # 找最小节点
current = self # 把当前节点赋值给变量(指针)
while current.hasLeftChild(): # 如果当前节点有左子就循环
current = current.leftChild # 当前指针就指向左子
return current # 返回最小节点
def spliceOut(self): # 删除后继节点
if self.isLeaf(): # 如果没子节点
if self.isLeftChild(): # 如果自己是左子
self.parent.leftChild = None # 把他父亲的左子变成空
else: # 反之自己是右子
self.parent.rightChild = None # 把他父亲的右子变成空
elif self.hasAnyChildren(): # 如果有子节点
if self.hasLeftChild(): # 他有左子
if self.isLeftChild(): # 他自己也是左子
self.parent.leftChild = self.leftChild # 让他的儿子对爷爷叫爸爸
else: # 他自己是右子
self.parent.rightChild = self.leftChild # 他父亲的右子等于他的左子
self.leftChild.parent = self.parent # 他左子的父亲等于他的父亲
else: # 他有右子
if self.isLeftChild(): # 他自己也是左子
self.parent.leftChild = self.rightChild # 他父亲的左子等于他的右子
else: # 他自己是右子
self.parent.rightChild = self.rightChild # 他父亲的右子等于他的右子
self.rightChild.parent = self.parent # 他右子的父亲等于他的父亲
class TreeNode:
def __init__(self, key, val, left=None, right=None, parent=None):
self.key = key # 键
self.payload = val # 值
self.leftChild = left # 左子
self.rightChild = right # 右子
self.parent = parent# 指针
self.balanceFactor = 0 # 平衡因子
def height(self): # 树高
height_l = 0
height_r = 0
if self.isLeaf():
return 0
if self.leftChild:
height_l = self.leftChild.height()
if self.rightChild:
height_r = self.rightChild.height()
return max(height_l, height_r) + 1
def hasLeftChild(self): # 是否有左子(none就是没有)
return self.leftChild
def hasRightChild(self): # 是否有右子
return self.rightChild
def hasAnyChildren(self): # 是否有孩子
return self.rightChild or self.leftChild
def hasBothChildren(self): # 是否有两孩子
return self.rightChild and self.leftChild
def isLeftChild(self): # 是不是父节点左子
return self.parent and self.parent.leftChild == self
def isRightChild(self): # 是不是父节点右子
return self.parent and self.parent.rightChild == self
def isRoot(self): # 是不是根节点
return not self.parent
def isLeaf(self): # 是不是叶子节点
return not (self.rightChild or self.leftChild)
def hasAnyChildren(self): # 是否有孩子
return self.rightChild or self.leftChild
def replaceNodeData(self, key, value, lc, rc): # 替换(键,值左子,右子)
self.key = key # 键
self.payload = value # 值
self.leftChild = lc # 左子
self.rightChild = rc # 右子
if self.hasLeftChild(): # 如果有左子
self.leftChild.parent = self # 左子的指针就指向我自己
if self.hasRightChild(): # 如果有右子
self.rightChild.parent = self # 右子的指针就指向我自己
def __iter__(self): # 二叉搜索树迭代器
if self: # 当前节点不为空
if self.hasLeftChild(): # 当前节点有左子
for elem in self.leftChild: # 遍历左子
yield elem # 生成数据
yield self.key #
if self.hasRightChild(): # 当前节点有右子
for elem in self.rightChild: # 遍历右子
yield elem # 生成数据
if __name__ == '__main__':
tree = BinarySearchTree()
tree[1] = 'a'
tree[2] = 'b'
tree[3] = 'c'
tree[4] = 'd'
tree[5] = 'e'
tree[6] = 'f'
tree[7] = 'g'
tree[8] = 'h'
tree[9] = 'i'
tree[10] = 'j'
tree[10] = 'x'
print('长度为', len(tree))
print('查找6的值', tree[6]) # 查找
print(6 in tree)
print('迭代输出value')
for a in tree:
print(tree[a])
print('迭代输出key')
for key in tree:
print(key)
#print(tree)
print('高度为', tree.height())
print('长度为', len(tree))
6.创建限定大小的二叉堆。也就是说,堆只保持n个最重要的元素。如果堆的大小超过 了n,就会舍弃最不重要的元素。
"""6.创建限定大小的二叉堆。也就是说,堆只保持n个最重要的元素。
如果堆的大小超过了n,就会舍弃最不重要的元素"""
class BinaryHeap: # 二叉堆类
def __init__(self, maxsize): # 定义属性(限定长度)
self.heapList = [0] # 定义二叉列表
self.currentSize = 0 # 定义长度
self.maxsize = maxsize # 限定长度
def percUp(self, i): # # 处理上移(实例,下标)
while i // 2 > 0: # 如果下标除二取整的数大于零
if self.heapList[i] < self.heapList[i // 2]: # 当前节点如果他小于了父节点
temp = self.heapList[i // 2]
self.heapList[i // 2] = self.heapList[i] # 调换位置
self.heapList[i] = temp
i = i // 2 # 寻找这个值的父节点(再与爷爷比较)
def insert(self, k): # 定义添加
self.heapList.append(k) # 添加到最后
self.currentSize = self.currentSize + 1 # 长度加一
self.percUp(self.currentSize) # 调用处理上移方法
def percDown(self, i): # 处理下移
while (i * 2) <= self.currentSize: # 如果i*2小于等于长度说明有左子
mc = self.minChild(i) # 拿到最小值下标
if self.heapList[i] > self.heapList[mc]: # 如果当前左子比左右孙大就交换它俩
temp = self.heapList[i]
self.heapList[i] = self.heapList[mc] # 调换位置
self.heapList[mc] = temp
i = mc # 把当前节点带到下一辈再进行比较
def minChild(self, i): # 找到最小值
if i * 2 + 1 > self.currentSize: # 如果i*2+1(右子)大于长度说明没有右子
return i * 2 # 返回左子
else: # 反之
if self.heapList[i*2] < self.heapList[i*2+1]: # 如果左子节点小于右子节点
return i * 2 # 返回左子节点下标
else: # 反之
return i * 2 + 1 # 返回右子节点下标
def delMin(self): # 定义删除
retval = self.heapList[1] # 获取根节点的值
self.heapList[1] = self.heapList[self.currentSize] # 把列表最后一个元素赋值到第一个
self.currentSize = self.currentSize - 1 # 列表长度-1
self.heapList.pop() # 删除列表最后一位
self.percDown(1) # 向下处理
return retval # 返回根节点的值
def buildHeap(self, alist): # 定义顺序输出函数(构建堆)
if len(alist) > self.maxsize: # 如果列表长度大于限定长度
alist = alist[:self.maxsize] # 只保留限定长度
i = len(alist) // 2 # 从儿子辈开始比较
self.currentSize = len(alist) # 传入列表长度为堆列表长度
self.heapList = [0] + alist[:] # 传入列表全部值前面再加个0赋值给堆列表
while (i > 0): # 如果i大于零
self.percDown(i) # 调用向下处理方法
i -= 1 # 长度减一
if __name__ == '__main__':
heap = BinaryHeap(10) # 创建对象(限定长度)
alist = [11, 5, 9, 21, 17, 19, 18, 27, 14, 33, 90, 88]
heap.buildHeap(alist) # 构建堆
print(heap.heapList) # 打印堆
7.整理printexp函数,去掉数字周围多余的括号。
"""7.整理printexp函数,去掉数字周围多余的括号"""
import operator
class BinaryTree:
# 初始化二叉树
def __init__(self, rootObj): # 根节点
self.root = rootObj # 根节点
self.leftChild = None # 左子
self.rightChild = None # 右子
# 插入左子树
def insertLeft(self, newNode):
if self.leftChild == None: # 若左子树为空,则
self.leftChild = BinaryTree(newNode) # 直接生成左子树
else:
t = BinaryTree(newNode) # 生成初始二叉树
t.leftChild = self.leftChild # 将原左子树赋值给新二叉树的左子树
self.leftChild = t # 再将新二叉树赋值给原二叉树的左子树
# 插入右子树
def insertRight(self, newNode):
if self.rightChild == None:
self.rightChild = BinaryTree(newNode)
else:
t = BinaryTree(newNode)
t.rightChild = self.rightChild
self.rightChild = t
# 获取右子树
def getRightChild(self):
return self.rightChild
# 获取左子树
def getLeftChild(self):
return self.leftChild
# 设置根节点值
def setRootVal(self, obj):
self.root = obj
# 获取根节点值
def getRootVal(self):
return self.root
# 中序遍历函数
def inorder(tree):
if tree: # 若树不为None,则
inorder(tree.getLeftChild()) # 中序遍历左子树
print(tree.getRootVal()) # 打印根节点值
inorder(tree.getRightChild()) # 中序遍历右子树
# 后序遍历函数
def postorder(tree):
if tree: # 若树不为None,则
postorder(tree.getLeftChild()) # 后序遍历左子树
postorder(tree.getRightChild()) # 后序遍历右子树
print(tree.getRootVal()) # 打印根节点值
# 前序遍历函数
def preorder(tree):
if tree: # 若树不为None,则
print(tree.getRootVal()) # 打印根节点值
preorder(tree.getLeftChild()) # 前序遍历左子树
preorder(tree.getRightChild()) # 前序遍历右子树
# 形成表达式
def printexp(tree):
sVal = "" # 表达式初始为空字符
if tree: # 有树
sVal = '(' + printexp(tree.getLeftChild()) # (+左子
sVal = sVal + str(tree.getRootVal()) # (+左子+根节点
sVal = sVal + printexp(tree.getRightChild()) + ')' # (+左子+根节点+右子+)
return sVal
# # 改进版(去掉数字周围多余括号的表达式)
def printexp1(tree):
sVal = '' # 表达式初始为空字符
if tree: # 有树
if tree.leftChild == None and tree.rightChild == None: # 无左子和无右子
sVal = sVal + str(tree.getRootVal()) # 根节点
else: # 反之
sVal = '(' + printexp1(tree.getLeftChild()) # (+左子
sVal = sVal + str(tree.getRootVal()) # (+左子+根节点
sVal = sVal + printexp1(tree.getRightChild()) + ')' # (+左子+根节点+右子+)
return sVal
# 后续计算表达式的值
def postordereval(tree):
# 定义子典{操作符为键:对应的函数为值}
opers = {'+':operator.add, '-':operator.sub, '*':operator.mul, '/':operator.truediv}
res1 = None # 左子
res2 = None # 右子
if tree: # 有树
res1 = postordereval(tree.getLeftChild()) # 第归左子
res2 = postordereval(tree.getRightChild()) # 第归右子
if res1 and res2: # 有左子和右子
return opers[tree.getRootVal()](res1,res2) # 调用字典里对应的函数进行计算
else: # 每左子和右子
return tree.getRootVal() # 返回根节点
# 树高
def height(tree):
if tree == None: # 出口
return -1
else: # max(递归左子,递归右子)
return 1 + max(height(tree.leftChild), height(tree.rightChild))
t = BinaryTree(7) # 创建对象(根节点)
t.insertLeft(3) # 添加(左子)
t.insertRight(9) # 添加(右子)
inorder(t) # 中序遍历
x = BinaryTree('*') # 创建对象(根节点)
x.insertLeft('+') # 添加(左子)
l = x.getLeftChild() # 获取左子
l.insertLeft(4) # 添加(左子)
l.insertRight(5) # 添加(右子)
x.insertRight(7) # 添加(右子)
print(printexp(x)) # 原版
print(printexp1(x)) # 改进版(去掉数字周围多余括号的表达式)
print(postordereval(x)) # 计算表达式的值
print(height(x)) # 树高
8.使用buildHeap方法,针对列表写一个时间复杂度为O ( l o g n ) O(logn)O(logn)的 排序函数。
class BinaryHeap:
def __init__(self, maxsize):
self.heapList = [0] # 装数据的列表
self.currentSize = 0 # 列表长度
self.maxsize = maxsize # 堆的最大长度
def percUp(self, i): # 处理上移(下标)
while i // 2 > 0: # 只要下标大于0就循环
if self.heapList[i] < self.heapList[i // 2]: # 列表下标的直大于他的父节点
tmp = self.heapList[i // 2] # 交换值
self.heapList[i // 2] = self.heapList[i]
self.heapList[i] = tmp
i = i // 2 # 此时下标就是父节点的位置然后继续向上比较
# 新加元素
def insert(self, k): # 添加(数据)
self.heapList.append(k) # 把数据条件到列表
self.currentSize = self.currentSize + 1 # 列表长度加1
self.percUp(self.currentSize) # 调用处理上移方法(下标)
def percDown(self, i): # 处理下移(下标)
while (i * 2) <= self.currentSize: # 下标只要等于小于列表长度
mc = self.minChild(i) # 调用找最小值方法得出最小子节点(下标)
if self.heapList[i] > self.heapList[mc]: # 如果当前节点大于他的子节点
tmp = self.heapList[i] # 就交换数据
self.heapList[i] = self.heapList[mc]
self.heapList[mc] = tmp
i = mc # 此时下标就是子节点的位置然后继续向下比较
def minChild(self, i): # 找最小值方法(下标)
if i * 2 + 1 > self.currentSize: # 如果超出了列表长度就没有右子
return i * 2 # 返回左子
else: # 没有超出列表长度
if self.heapList[i*2] < self.heapList[i*2 + 1]: # 左子小于右子
return i * 2 # 返回左子
else: # 右子大
return i * 2 + 1 # 返回左子
## 从二叉堆中删除最小的元素
def delMin(self): # 删除最小的元素
retval = self.heapList[1] # 把列表第一个赋值给变量
self.heapList[1] = self.heapList[self.currentSize] # 再把列表最后一个拿上来顶替
self.currentSize = self.currentSize - 1 # 列表长度-1
self.heapList.pop() # 删除列表最后一个
self.percDown(1) # 再把顶替第一的进行向下处理
return retval # 返回列表第一个
# 根据元素列表构建堆
def buildHeap(self, alist): # 对列表进行排序(列表)
if len(alist) > self.maxsize: # 列表长度>堆最大长度
alist = alist[:self.maxsize] # 从左开始只取出堆最大长度的元素
i = len(alist) // 2 # 返回列表长度的一半
self.currentSize = len(alist) # 返回传入列表长度赋值给堆列表长度
self.heapList = [0] + alist[:] # 把传入列表的数据取出来前面加个0赋值给堆列表
while (i > 0): # 下标大于0就循环
self.percDown(i) # 调用处理下移
i -= 1 # 长度-1
def sort(alist): # 排序
heap = BinaryHeap(13) # 创建对象
blist = [0] # 定义空堆
heap.buildHeap(alist) # 重新排列
for i in range(1, len(alist) + 1): # 列表长度-1
if heap.currentSize > 0: # 列表长度
blist += [heap.heapList[1]] # 把堆列表的元素赋值给新定义的空堆
heap.buildHeap(heap.heapList[2:]) # 把第二个到最后重新排列
print(blist) # 打印堆
if __name__ == '__main__':
alist = [9, 6, 5, 2, 39, 16, 15, 12, 389, 26, 25, 22, 33]
sort(alist)
9.写一个函数,以数学表达式解析树为参数,计算各变量的导数。
&
10.将二叉树实现为最大堆。
"""10.将二叉树实现为最大堆。最大堆的实现"""
class MaxHeap():
def __init__(self, maxSize=None):
self.maxSize = maxSize
self.li = [None] * maxSize
self.count = 0
def length(self):
#求数组的长度
return self.count
def show(self):
if self.count <= 0:
print('null')
else:
print(self.li[: self.count])
def add(self, value):
if self.count >= self.maxSize: # 判断是否数组越界
raise Exception('full')
self.li[self.count] = value # 将新节点增加到最后
self._shift_up(self.count) # 递归构建大堆
self.count += 1
def _shift_up(self, index):
#往大堆中添加元素,并保证根节点是最大的值:
#1.增加新的值到最后一个结点,在add实现; 2.与父节点比较,如果比父节点值大,则交换
if index > 0:
parent = (index - 1) // 2 # 找到根节点
if self.li[index] > self.li[parent]: # 交换结点
self.li[index], self.li[parent] = self.li[parent], self.li[index]
self._shift_up(parent) # 继续递归从底往上判断
def extract(self):
#弹出最大堆的根节点,即最大值
#1.删除根结点,将最后一个结点作为更结点 ; 2.判断根结点与左右结点的大小,交换左右结点较大的
if not self.count:
raise Exception('null')
value = self.li[0]
self.count -= 1
self.li[0] = self.li[self.count] # 将最后一个值变为第一个
self._shift_down(0)
return value
def _shift_down(self, index):
# 1.判断是否有左子节点并左大于根,左大于右;2.判断是否有右子节点,右大于根
left = 2 * index + 1
right = 2 * index + 2
largest = index
#判断条件
# 下面2个条件包含了,判断左右结点那个大的情况。如果为3, 4, 5,:
# 第一个判断条件使得largest = 1,再执行第二个条件,则判断其左结点与右结点的大小
if left < self.length() and self.li[left] > self.li[largest]:
largest = left
if right < self.length() and self.li[right] > self.li[largest]:
largest = right
if largest != index: # 将 两者交换
self.li[index], self.li[largest] = self.li[largest], self.li[index]
self._shift_down(largest)
if __name__ == '__main__':
m = MaxHeap(10)
import numpy as np
np.random.seed(123)
num = np.random.randint(100, size =10) #创建随机的10个数
print(m.length())
for i in num:
m.add(i)
m.show()
print(m.length())
for i in range(10):
print(m.extract(), end=' ,')
11.使用BinaryHeap类。实现一个叫做PriorityQueue的新类。为PriorityQueue类实 现构造方法,以及enqueue方法和dequeue方法。
"""11.使用BinaryHeap类。实现一个叫做PriorityQueue的新类
。为PriorityQueue类实现构造方法,以及enqueue方法和dequeue方法"""
class BinaryHeap:
# 新建二叉堆
def __init__(self):
self.heapList = [0] # 装数据的列表
self.currentSize = 0 # 列表长度
def percUp(self, i): # 处理上移(下标)
while i // 2 > 0: # 只要下标大于0就循环
if self.heapList[i] < self.heapList[i // 2]: # 列表下标的直大于他的父节点
tmp = self.heapList[i // 2] # 交换值
self.heapList[i // 2] = self.heapList[i]
self.heapList[i] = tmp
i = i // 2 # 此时下标就是父节点的位置然后继续向上比较
# 新加元素
def insert(self, k): # 添加(数据)
self.heapList.append(k) # 把数据条件到列表
self.currentSize = self.currentSize + 1 # 列表长度加1
self.percUp(self.currentSize) # 调用处理上移方法(下标)
def percDown(self, i): # 处理下移(下标)
while (i * 2) <= self.currentSize: # 下标只要等于小于列表长度
mc = self.minChild(i) # 调用找最小值方法得出最小子节点(下标)
if self.heapList[i] > self.heapList[mc]: # 如果当前节点大于他的子节点
tmp = self.heapList[i] # 就交换数据
self.heapList[i] = self.heapList[mc]
self.heapList[mc] = tmp
i = mc # 此时下标就是子节点的位置然后继续向下比较
def minChild(self, i): # 找最小值方法(下标)
if i * 2 + 1 > self.currentSize: # 如果超出了列表长度就没有右子
return i * 2 # 返回左子
else: # 没有超出列表长度
if self.heapList[i*2] < self.heapList[i*2 + 1]: # 左子小于右子
return i * 2 # 返回左子
else: # 右子大
return i * 2 + 1 # 返回左子
## 从二叉堆中删除最小的元素
def delMin(self): # 删除最小的元素
retval = self.heapList[1] # 把列表第一个赋值给变量
self.heapList[1] = self.heapList[self.currentSize] # 再把列表最后一个拿上来顶替
self.currentSize = self.currentSize - 1 # 列表长度-1
self.heapList.pop() # 删除列表最后一个
self.percDown(1) # 再把顶替第一的进行向下处理
return retval # 返回列表第一个
## 根据元素列表构建堆
def builgHeap(self, alist): # 对列表进行排序(列表)
i = len(alist) // 2 #
self.currentSize = len(alist) # 返回传入列表长度赋值给列表长度
self.heapList = [0] + alist[:] # 把传入列表的数据取出来前面加个0定义成
while (i > 0): # 下标大于0就循环
self.percDown(i) #
i = i - 1
class PriorityQueue: # 优先队列
def __init__(self): # 初始为空的列表
self.items = []
def isEmpty(self): # 检查列表
return self.items == []
def enqueue(self, item): # 入队
self.items.append(item) # 添加列表尾部
heap = BinaryHeap() # 创建堆对象
heap.builgHeap(self.items) # 根据元素列表构建堆
self.items = heap.heapList[1:] # 取出堆列表赋值给队列
def dequeue(self): # 出队
return self.items.pop(0) # 删除列表第一个
def size(self): # 返回列表长度
return len(self.items)
if __name__ == '__main__':
q = PriorityQueue()
q.enqueue(5) # 进队
q.enqueue(2)
q.enqueue(3)
q.enqueue(6)
q.enqueue(1)
print(q.items) # 打印列表
q.dequeue() # 出队
q.dequeue()
print(q.items)
12.实现AVL树的delete方法。实现AVL的delete方法,要更新平衡因子,然后再平衡。
"""12.实现AVL树的delete方法。实现AVL的delete方法"""
def aaa(node): # 中序遍历
if node != None:
aaa(node.leftChild)
print(node.key)
aaa(node.rightChild)
class BinarySearchTree: # 二叉搜索树类
def __init__(self): # 初始属性
self.root = None # 根节点为空
self.size = 0 # 节点长度为0
def __str__(self):
return self.root
def length(self): # 返回长度
return self.size
def __len__(self): # 魔法方法返回长度
return self.size
def __iter__(self): # 实现for循环
return self.root.__iter__()
def height(self): # 返回树高
if self.root != None:
return self.root.height()
else:
print('没有树')
def put(self, key, value): # 主添加(键,值)
if self.root: # 不为空,有节点
self._put(key, value, self.root) # 调用辅助添加方法(键,值,指针)
else: # 反之
self.root = TreeNode(key, value) # 创建对象传入(键,值)
self.size = self.size + 1 # 节点长度+1
def _put(self, key, val, currentNode): # 副添加(键,值,指针)
if key < currentNode.key: # 如果传入的键小于当前节点的键
if currentNode.hasLeftChild(): # 当前节点有左子
self._put(key, val, currentNode.leftChild) # 递归调用左子去办
else: # 没左子
# 直接创建一个左子节点赋值给当前左子
currentNode.leftChild = TreeNode(key, val, parent=currentNode)
else: # 传入的键大于当前节点的键
if currentNode.hasRightChild(): # 当前节点有右子
self._put(key, val, currentNode.rightChild)# 递归调用右子去办
else:# 没右子
# 直接创建一个右子节点赋值给当前右子
currentNode.rightChild = TreeNode(key, val, parent=currentNode)
def __setitem__(self, key, value): # 像字典一样输入
self.put(key, value)
def get(self, key): # 主查找
if self.root: # 不为空,有节点
res = self._get(key, self.root) # 调用副查找
if res: # 如果找到了
return res.payload # 返回value
else: # 反之没找到
return None
else: # 反之为空
return None
def _get(self, key, currentNode): # 副查找方法(键,节点)
if not currentNode: # 如果节点为空
return None # 返回空
elif currentNode.key == key: # 如果节点的键等于你要找的键
return currentNode # 返回当前节点
elif key < currentNode.key: # 如果你要找的键小于当前节点的键
return self._get(key, currentNode.leftChild) # 就去左子树里找
else: # 反之你要找的键大于当前节点的键
return self._get(key, currentNode.rightChild) # 就去右子树里找
def __getitem__(self, key): # 像字典一样查找
return self.get(key)
def __contains__(self, key): # 检查树中是否有某个键(in方法)
if self._get(key, self.root):
return True
else:
return False
def delete(self, key): # 主删除(键)
if self.size > 1: # 节点长度>1
nodeToRemove = self._get(key, self.root) # 调用查找方法找到你要删除的键
if nodeToRemove: # 如果找到了
self.remove(nodeToRemove) # 调用删除副方法
self.size -= 1 # 节点长度-1
else: # 没找到了
print('错误,键不在树中')
# 节点长度==1就只有根节点了==你要找的
elif self.size == 1 and self.root.key == key:
self.root = None # 把根节点设为空
self.size = 0 # 节点长度为0
else:
print('错误,键不在树中')
def remove(self, currentNode): # 副删除方法
# 情况1.删除节点没有子节点
if currentNode.isLeaf(): # 如果是叶子节点
if currentNode == currentNode.parent.leftChild: # 如果是父节点的左子
currentNode.parent.leftChild = None # 就父节点的左子设为空
else: # 反之
currentNode.parent.rightChild = None # 就父节点的右子设为空
# 情况2.有一个节点
# 如果当前节点有左子和没右子
elif currentNode.hasLeftChild() and not currentNode.hasRightChild():
if currentNode.isLeftChild(): # 他自己是左子
# 当前左子的父亲等于当前节点的父亲
currentNode.leftChild.parent = currentNode.parent #
# 当前节点父亲的左子等于当前节点的左子
currentNode.parent.leftChild = currentNode.leftChild
elif currentNode.isRightChild():# 他自己是右子
# 当前右子的父亲等于当前节点的父亲等于当前节点的父亲
currentNode.rightChild.parent = currentNode.parent
# 当前节点父亲的右子等于当前节点的左子
currentNode.parent.rightChild = currentNode.leftChild
else: # 反之他没父节点就是根节点了(他儿子继承他父亲的一切)
currentNode.replaceNodeData(currentNode.leftChild.key,
currentNode.leftChild.payload,
currentNode.leftChild.leftChild,
currentNode.leftChild.rightChild)
# 如果当前节点有右子和没左子
elif currentNode.hasRightChild() and not currentNode.hasLeftChild():
if currentNode.isLeftChild():# 他自己是左子
# 当前右子的父亲等于当前节点的父亲等于当前节点的父亲
currentNode.rightChild.parent = currentNode.parent
# 当前节点父亲的左子等于当前节点的右子
currentNode.parent.leftChild = currentNode.rightChild
elif currentNode.isRightChild():# 他自己是右子
# 当前右子的父亲等于当前节点的父亲等于当前节点的父亲
currentNode.rightChild.parent = currentNode.parent
# 当前节点父亲的右子等于当前节点的右子
currentNode.parent.rightChild = currentNode.rightChild
else:# 反之他没父节点就是根节点了(他儿子继承他父亲的一切)
currentNode.replaceNodeData(currentNode.leftChild.key,
currentNode.leftChild.payload,
currentNode.leftChild.leftChild,
currentNode.leftChild.rightChild)
# 情况3.有二个节点
else: # 反之有二子
succ = currentNode.findSuccessor() # 调用寻找后继节点
succ.spliceOut() # 调用删除后继节点
currentNode.key = succ.key # 当前节点的键等于后继节点的键
currentNode.payload = succ.payload# 当前节点的值等于后继节点的值
def __delitem__(self, key): # 像字典一样删除
self.delete(key)
class TreeNode: # 节点类
def __init__(self, key, val, left=None, right=None, parent=None, succ=None, balanceFactor=0):
self.key = key # 键
self.payload = val # 值
self.leftChild = left # 左子
self.rightChild = right # 右子
self.parent = parent # 指针
self.succ = succ # 后继节点
self.balanceFactor = balanceFactor # 平衡因子
def height(self): # 树高
height_l = 0 # 左高
height_r = 0 # 右高
if self.leftChild: # 如果有左子
height_l = self.leftChild.height() # 左子高度
if self.rightChild: # 如果有右子
height_r = self.rightChild.height() # # 右子高度
return max(height_l, height_r) + 1 # 返回树高+1
def hasLeftChild(self): # 是否有左子(none就是没有)
return self.leftChild
def hasRightChild(self): # 是否有右子
return self.rightChild
def isLeftChild(self): # 是不是父节点左子
# 父节点不空和我父亲的左子是我自己
return self.parent and self.parent.leftChild == self
def isRightChild(self): # 是不是父节点右子
# 父节点不空和我父亲的右子是我自己
return self.parent and self.parent.rightChild == self
def isRoot(self): # 是不是根节点
return not self.parent # 是返回真,不是返回假
def isLeaf(self): # 是不是叶子节点
return not (self.rightChild or self.leftChild) # 左子右子只要有一个就返回真
def hasAnyChildren(self): # 是否有孩子
return self.rightChild or self.leftChild # 返回左子或右子
def hasBothChildren(self): # 是否有两孩子
return self.leftChild and self.rightChild # 返回左子和右子
def replaceNodeData(self, key, value, lc, rc): # 替换(键,值左子,右子)
self.key = key # 键
self.payload = value # 值
self.leftChild = lc # 左子
self.rightChild = rc # 右子
if self.hasLeftChild(): # 如果有左子
self.leftChild.parent = self # 左子的指针就指向我自己
if self.hasRightChild(): # 如果有右子
self.rightChild.parent = self # 右子的指针就指向我自己
def findSuccessor(self): # 寻找后继节点
succ = None # 后继节点先为空
if self.hasRightChild(): # 如果有右子
succ = self.rightChild.findMin() # 找右子树里最小的
else: # 反之没有右子
if self.parent: # 如果有父节点
if self.isLeftChild(): # 如果自己是左子
succ = self.parent # 后继节点是他的父节点
else: # 自己是右子
self.parent.rightChild = None # 先把自己设为空(不设为空就会查到自己)
succ = self.parent.findSuccessor() # 递归调用找后继
self.parent.rightChild = self # 父节点的右子是自己
return succ # 返回后继节点
def findMin(self): # 找最小节点
current = self # 把当前节点赋值给变量(指针)
while current.hasLeftChild(): # 如果当前节点有左子就循环
current = current.leftChild # 当前指针就指向左子
return current # 返回最小节点
def spliceOut(self): # 删除后继节点
if self.isLeaf(): # 如果没子节点
if self.isLeftChild(): # 如果自己是左子
self.parent.leftChild = None # 把他父亲的左子变成空
else: # 反之自己是右子
self.parent.rightChild = None # 把他父亲的右子变成空
elif self.hasAnyChildren(): # 如果有子节点
if self.hasLeftChild(): # 他有左子
if self.isLeftChild(): # 他自己也是左子
self.parent.leftChild = self.leftChild # 让他的儿子对爷爷叫爸爸
else: # 他自己是右子
self.parent.rightChild = self.leftChild # 他父亲的右子等于他的左子
self.leftChild.parent = self.parent # 他左子的父亲等于他的父亲
else: # 他有右子
if self.isLeftChild(): # 他自己也是左子
self.parent.leftChild = self.rightChild # 他父亲的左子等于他的右子
else: # 他自己是右子
self.parent.rightChild = self.rightChild # 他父亲的右子等于他的右子
self.rightChild.parent = self.parent # 他右子的父亲等于他的父亲
def __iter__(self): # 二叉搜索树迭代器
if self: # 当前节点不为空
if self.hasLeftChild(): # 当前节点有左子
for elem in self.leftChild: # 遍历左子
yield elem # 生成数据
yield self.key #
if self.hasRightChild(): # 当前节点有右子
for elem in self.rightChild: # 遍历右子
yield elem # 生成数据
class AVL(BinarySearchTree): # 更改为平衡二叉树(继承二叉搜索树类)
# 1.修改辅助添加
def _put(self, key, value, currentNode): # 辅助添加(键,值,指针)
if key < currentNode.key: # 如果传入的键小于当前节点的键
if currentNode.hasLeftChild(): # 当前节点有左子
self._put(key, value, currentNode.leftChild) # 递归调用左子去办
else: # 没左子
currentNode.leftChild = TreeNode( # 直接创建一个左子节点赋值给当前左子
key, value, parent=currentNode)
self.updateBalance(currentNode.leftChild) # 更新平衡因子
else: # 反之传入的键大于当前节点的键
if currentNode.hasRightChild(): # 当前节点有右子
self._put(key, value, currentNode.rightChild) # 递归调用右子去办
else: # 没右子
currentNode.rightChild = TreeNode( # 直接创建一个右子节点赋值给当前右子
key, value, parent=currentNode)
self.updateBalance(currentNode.rightChild) # 更新平衡因子
# 2.添加更新平衡因子(添加时用)
def updateBalance(self, node): # 更新平衡因子
# 如果节点的因子>1或节点的因子< -1
if node.balanceFactor > 1 or node.balanceFactor < -1:
self.rebalance(node) # 调用再平衡方法
return # 返回
if node.parent != None: # 如果当前节点父亲不为空
if node.isLeftChild(): # 如果当前节点是左子
node.parent.balanceFactor += 1 # 当前节点父亲的平衡因子+1
elif node.isRightChild(): # 如果当前节点是右子
node.parent.balanceFactor -= 1 # 当前节点父亲的平衡因子-1
if node.parent.balanceFactor != 0: # 当前节点父亲的平衡因子不等于0
self.updateBalance(node.parent) # 递归调用自己向上找
# 3.添加更新平衡因子(删除时用)
def updateBalance2(self, node): # 更新平衡因子
# 如果节点的因子>1或节点的因子< -1
if node.balanceFactor > 1 or node.balanceFactor <= -1:
self.rebalance(node) # 调用再平衡方法
return # 返回
if node.parent != None: # 如果当前节点父亲不为空
if node.isLeftChild(): # 如果当前节点是左子
node.parent.balanceFactor -= 1 # 当前节点父亲的平衡因子-1
elif node.isRightChild(): # 如果当前节点是右子
node.parent.balanceFactor += 1 # 当前节点父亲的平衡因子+1
if node.parent.balanceFactor != 0: # 当前节点父亲的平衡因子不等于0
self.updateBalance2(node.parent) # 递归调用自己向上找
# 4.修改删除后继节点
def spliceOut2(self): # 删除后继节点
if self.isLeaf():# 如果没子节点
if self.isLeftChild():# 如果自己是左子
self.parent.leftChild = None# 把他父亲的左子变成空
self.parent.balanceFactor -= 1 # 他父亲的平衡因子-1
else:# 反之自己是右子
self.parent.rightChild=None # 把他父亲的右子变成空
self.parent.balanceFactor += 1# 他父亲的平衡因子+1
elif self.hasAnyChildren():# 如果有子节点
if self.hasLeftChild():# 他有左子
if self.isLeftChild():# 他自己也是左子
self.parent.leftChild = self.leftChild #他父亲的左子等于他的左子
else:# 反之他自己是右子
self.parent.rightChild=self.leftChild # 把他父亲的右子等于他的左子
self.leftChild.parent=self.parent # 他左子的父亲等于他的父亲
else:# 反之他有右子
if self.isLeftChild():# 他自己也是左子
self.parent.leftChild = self.rightChild#他父亲的左子等于他的右子
self.parent.balanceFactor -= 1 # 他父亲的平衡因子-1
else:# 反之自己是右子
self.parent.rightChild = self.rightChild# 把他父亲的右子等于他的右子
self.parent.balanceFactor += 1# 他父亲的平衡因子+1
self.rightChild.parent = self.parent# 他右子的父亲等于他的父亲
# 5.添加左旋
def rotateLeft(self, rotRoot): # 左旋方法
newRoot = rotRoot.rightChild # 新节点=旧节点的右子
rotRoot.rightChild = newRoot.leftChild # 老节点的右子=新节点的左子
if newRoot.leftChild != None: # 新节点的左子不为空
newRoot.leftChild.parent = rotRoot # 新节点的左子的爸爸=老节点
newRoot.parent = rotRoot.parent # 新节点的爸爸=老节点的爸爸
if rotRoot.isRoot(): # 如果旧节点是根节点
self.root = newRoot # 根节点是新节点
else: # 反旧节点不是之根节点
if rotRoot.isLeftChild(): # 如果旧节点是左子
rotRoot.parent.leftChild = newRoot # 旧节点爸爸的左子=新节点
else: # 如果旧节点是右子
rotRoot.parent.rightChild = newRoot # 旧节点爸爸的右子=新节点
newRoot.leftChild = rotRoot # 新节点的左子 = 旧节点
rotRoot.parent = newRoot # 旧节点的爸爸 = 新节点
# 旧因子=旧因子+1-()
rotRoot.balanceFactor = rotRoot.balanceFactor + \
1 - min(newRoot.balanceFactor, 0)
# 新因子=新因子
newRoot.balanceFactor = newRoot.balanceFactor + \
1 + max(rotRoot.balanceFactor, 0)
# 6.添加右旋
def rotateRight(self, rotRoot): # 右旋方法
newRoot = rotRoot.leftChild # 新节点=旧节点的左子
rotRoot.leftChild = newRoot.rightChild # 旧节点的左子=新节点的右
if newRoot.rightChild != None: # 如果新节点的右子不等于空
newRoot.rightChild.parent = rotRoot # 新节点右子的爸爸 = 旧节点
newRoot.parent = rotRoot.parent # 新节点的爸爸 = 旧节点的爸爸
if rotRoot.isRoot(): # 如果旧节点是根节点
self.root = newRoot # 根节点就是新节点
else: # 反之旧节点不是根节点
if rotRoot.isRightChild(): # 如果旧节点是右子
rotRoot.parent.rightChild = newRoot # 旧节点的爸爸的右子 = 新节点
else: # 反之旧节点是左子
rotRoot.parent.leftChild = newRoot # 旧节点的爸爸的左子 = 新节点
newRoot.rightChild = rotRoot # 新节点右子 = 旧节点
rotRoot.parent = newRoot # 旧节点的爸爸 = 新节点
# 旧因子=旧因子-1-max(新因子,0)
rotRoot.balanceFactor = rotRoot.balanceFactor - \
1 - max(newRoot.balanceFactor, 0)
# 新因子=新因子-1+man(新因子,0)
newRoot.balanceFactor = newRoot.balanceFactor - \
1 + min(rotRoot.balanceFactor, 0)
# 7.添加实现再平衡
def rebalance(self, node): # 实现再平衡
if node.balanceFactor < 0: # 当前节点因子<0(右高)
if node.rightChild.balanceFactor > 0: # 当前节点右子因子>0(右子高)
self.rotateRight(node.rightChild) # 先对根节点的右子做一个右旋转
self.rotateLeft(node) # 再对根节点做一个左旋转
else:
self.rotateLeft(node) # 直接对根节点做一个左旋转
elif node.balanceFactor > 0: # 当前节点因子>0(左高)
if node.leftChild.balanceFactor < 0: # 当前节点左子因子>0(左子高)
self.rotateLeft(node.leftChild) # 先对根节点的左子做一个左旋转
self.rotateRight(node) # 再对根节点做一个右旋转
else:
self.rotateRight(node) # 直接对根节点做一个左旋转
# 8.修改主删除
def delete1(self, key):# 删除(键)
if self.size > 1: # 节点长度>1
nodeToRemove = self._get(key, self.root) # 调用查找方法找到你要删除的键
if nodeToRemove:# 如果找到了
self.remove1(nodeToRemove) # 调用删除副方法
self.size -= 1 # 节点长度-1
else:# 没找到了
raise KeyError('错误,键不在树中')
elif self.size == 1 and self.root.key == key:# 节点长度==1就只有根节点了==你要找的
self.root = None # 把根节点设为空
self.size = 0# 节点长度为0
else:
raise KeyError('错误,键不在树中')
# 9.修改副删除
def remove1(self, currentNode):# 副删除方法
# 情况1.删除节点没有子节点
if currentNode.isLeaf():# 如果是叶子节点
if currentNode == currentNode.parent.leftChild:# 如果是父节点的左子
currentNode.parent.leftChild = None# 就父节点的左子设为空
currentNode.parent.balanceFactor -= 1# 当前节点父亲的平衡因子-1
else:# 反之
currentNode.parent.rightChild = None# 就父节点的右子设为空
currentNode.parent.balanceFactor += 1# 当前节点父亲的平衡因子+1
self.updateBalance2(currentNode.parent) # 更新平衡因子
# 情况2.有一个节点
# 如果当前节点有左子和没右子
elif currentNode.hasLeftChild() and not currentNode.hasRightChild():
if currentNode.isLeftChild():# 他自己是左子
# 当前左子的父亲等于当前节点的父亲
currentNode.leftChild.parent = currentNode.parent
# 当前节点父亲的左子等于当前节点的左子
currentNode.parent.leftChild = currentNode.leftChild
# 当前节点父亲的平衡因子-1
currentNode.parent.balanceFactor -= 1
elif currentNode.isRightChild():# 他自己是右子
# 当前右子的父亲等于当前节点的父亲等于当前节点的父亲
currentNode.rightChild.parent = currentNode.parent
# 当前节点父亲的右子等于当前节点的左子
currentNode.parent.rightChild = currentNode.leftChild
# 当前节点父亲的平衡因子+1
currentNode.parent.balanceFactor += 1
else:# 反之他没父节点就是根节点了(他儿子继承他父亲的一切)
currentNode.replaceNodeData(currentNode.leftChild.key,
currentNode.leftChild.payload,
currentNode.leftChild.leftChild,
currentNode.leftChild.rightChild)
#self.updateBalance2(currentNode.parent) # 更新平衡因子
# 如果当前节点有右子和没左子
elif currentNode.hasRightChild() and not currentNode.hasLeftChild():
if currentNode.isLeftChild():# 他自己是左子
# 当前右子的父亲等于当前节点的父亲等于当前节点的父亲
currentNode.rightChild.parent = currentNode.parent
# 当前节点父亲的左子等于当前节点的右子
currentNode.parent.leftChild = currentNode.rightChild
# 当前节点父亲的平衡因子-1
currentNode.parent.balanceFactor -= 1
elif currentNode.isRightChild():# 他自己是右子
# 当前右子的父亲等于当前节点的父亲等于当前节点的父亲
currentNode.rightChild.parent = currentNode.parent
# 当前节点父亲的右子等于当前节点的右子
currentNode.parent.rightChild = currentNode.rightChild
# 当前节点父亲的平衡因子+1
currentNode.parent.balanceFactor += 1
else: # 反之他没父节点就是根节点了(他儿子继承他父亲的一切)
currentNode.replaceNodeData(currentNode.rightChild.key,
currentNode.rightChild.payload,
currentNode.rightChild.leftChild,
currentNode.rightChild.rightChild)
#self.updateBalance2(currentNode.parent) # 更新平衡因子
#currentNode.balanceFactor = 0
# 情况3.有二个节点
else:# 反之有二子
succ = currentNode.findSuccessor()# 调用寻找后继节点
succ.spliceOut()# 调用删除后继节点
self.updateBalance2(currentNode) # 更新平衡因子
currentNode.key = succ.key# 当前节点的键等于后继节点的键
currentNode.payload = succ.payload# 当前节点的值等于后继节点的值
# 10.查看中序遍历和平衡因子(中序遍历非递归写法)
def inorder(self): # 中序遍历
currentNode = self.root # 根节点赋值给变量
while currentNode: #
beginNode = currentNode
currentNode = currentNode.leftChild #
while beginNode.findSuccessor():
print(beginNode.key, beginNode.balanceFactor)
beginNode = beginNode.findSuccessor()
print(beginNode.key, beginNode.balanceFactor) #
def inorder2(self):
currentNode = self.root
while currentNode:
beginNode = currentNode
currentNode = currentNode.leftChild
while beginNode.succ:
print(beginNode.key)
beginNode = beginNode.succ
print(beginNode.key)
if __name__ == '__main__':
tree = AVL()
tree[1] = 'a'
tree[2] = 'b'
tree[3] = 'c'
tree[4] = 'd'
tree[5] = 'e'
tree[6] = 'f'
tree[7] = 'g'
tree[8] = 'h'
tree[9] = 'i'
tree[10] = 'j'
print('原始高度为:', tree.height())
print('原始长度为:',len(tree))
print('查找5在不在:', 5 in tree)
print('查找1的值:', tree[1]) # 查找
#tree.delete1(1)
#tree.delete1(2)
# tree.delete1(3)
#tree.delete1(4)
#tree.delete1(5)
#tree.delete1(6)
# tree.delete1(7)
#tree.delete1(8)
#tree.delete1(9)
#tree.delete1(10)
print('删除后高度为', tree.height())
print('删除后长度为', len(tree))
print('-'*20)
print('迭代输出value')
for a in tree:
print(tree[a])
print('-'*20)
print('迭代输出key')
for key in tree:
print(key)
print('-'*20)
print(aaa(tree.root))
tree.inorder()
# tree.inorder2()