二叉查找树
二叉查找树,也称二叉搜索树,或二叉排序树。其定义也比较简单,要么是一颗空树,要么就是具有如下性质的二叉树:
- 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 任意节点的左、右子树也分别为二叉查找树;
- 没有键值相等的节点。
二叉查找树的增删改查
首先创建节点类,包括值,左子节点,右子节点,三个属性
class Node():
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = righ
创建树类,包括增,删,查,取最大,取最小,遍历(中序遍历)方法
增:
- 首先判断是否存在根节点,如果不存在则直接创建节点,作为根节点返回
- 判断输入的值是否大于根节点的值,如果大于,则将其右子节点作为根节点;如果小于根节点的值,则将左子节点作为根节点的值,循环上述操作,直到所查询的根节点为None,创建Node实例,作为其上一轮遍历节点的子节点
class Tree:
def insert(self, value, root):
if root == None:
root = Node(value)
elif value > root.value:
root.right = self.insert(value, root.right)
else:
root.left = self.insert(value, root.left)
return root
查:
- 首先判断根节点是否存在,如果不存在则返回-1
- 用被查找的值与根节点的值进行比较,如果相等则返回根节点,如果大于根节点的值,则将其右子节点作为根几点,如果小于根节点的值,则将左子节点作为根节点,继续查找
- 如果最终root的值为-1则表示该值不存在返回-1
def query(self, value, root):
if root == None:
return -1
elif value > root.value:
return self.query(value, root.right)
elif value < root.value:
return self.query(value, root.left)
else:
return root
寻找最大、最小值
- 由于二叉查找树的右子节点的值总是大于父节点,所以只要不停地寻找根节点的右子,右子孙节点即可
- 如果右子、孙节点为None,则说明该节点的值即为树种的最大值
- 最小值与最大值相反
def findmax(self, root):
if root == None:
return
elif root.right:
return self.findmax(root.right)
else:
return root
def findmine(self, root):
if root == None:
return
elif root.left:
return self.findmine(root.left)
else:
return root
删:
- 首先判断该树是否为空
- 在树中查找该节点,如果不存在则直接返回
- 从根节点开始,查找到该节点,分三种情况
- 如果该节点没有子节点,则直接将其删除
- 如果该节点存在左子节点或右子节点,则将该节点的父节点指向该节点的左子节点或右子节点
- 如果该节点同时存在左子节点和右子节点,则互换该节点和该节点右子树中的最小值的节点(或互换该节点和该节点左子树的最大值),以互换该节点和右子树种的最大值为例,具体过程如下
- 找到右子树中的最小值对应节点
- 该节点右子树最小值赋值给该节点,不改变该节点的left,right
- 删除右子树种的最小值节点,重复上述步骤
def delNode(self,root, value):
'''删除二叉搜索树中值为value的点'''
if self.query(value, root) == -1:
return
if root == None:
return
if value < root.value:
root.left = self.delNode(value,root.left)
elif value > root.value:
root.right = self.delNode(root.right,value)
# 当value == root.value时,分为三种情况:只有左子树或者只有右子树、有左右子树、即无左子树又无右子树
else:
if root.left and root.right:
# 既有左子树又有右子树,则需找到右子树中最小值节点
temp = self.findmine(root.right)
root.value = temp.value
# 再把右子树中最小值节点删除
root.right = self.delNode(root.right,temp.value)
elif root.right == None and root.left == None:
# 左右子树都为空
root = None
elif root.right == None:
# 只有左子树
root = root.left
elif root.left == None:
# 只有右子树
root = root.right
return root
中序遍历
# 递归中序遍历
def pre_order(self, root):
if root == None:
return
self.pre_order(root.left)
print(root.value)
self.pre_order(root.right)
# 迭代中序遍历
def pre_oder_2(root):
# ans列表用于存储排序后的数据,stack为栈存储逆序的ans,先进后出
ans,stack = [],[]
cur = root
while cur or stack:
if cur:
# 将根节点左子树压入栈中
stack.append(cur)
cur = cur.left
else:
# 取最左侧节点,即为最小值
cur = stack.pop()
ans.append(cur)
# 取最左侧节点的右子节点,如果存在右子树,则将其压入栈中
cur = cur.right
获取树的高度
分别获取左子树和右子树的高度,取二者较大者,再加1即为整个树的高度
def get_depth(self, root):
if root == None:
return 0
nright = self.get_depth(root.right)
nleft = self.get_depth(root.left)
return max(nleft, nright) + 1