二叉搜索树
1. 定义
二叉搜索树(BST)也称二叉排序树或二叉查找树
二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:
- 非空左子树的所有键值小于其根结点的键值
- 非空右子树的所有键值大于其根结点的键值
- 左、右子树都是二叉搜索树
2. 特殊函数
- BinTree Find(ElementType X,BinTree BST):从二叉搜索树 BST 中查找元素 X,返回其所在结点地址
- BinTree FindMin(BinTree BST):从二叉搜索树 BST 中查找并返回最小元素所在结点的地址
- BinTree FindMax(BinTree BST):从二叉搜索树 BST 中查找并返回最大元素所在结点的地址
- BinTree Insert(ElementType X,BinTree BST):插入一个元素进 BST
- BinTree Delete(ElementType X,BinTree BST):从 BST 中删除一个元素
1. 查找
查找从根结点开始,如果树为空,返回 NULL
若搜索树不为空,则根结点键值和 X 进行比较,并进行不同处理:
- 若 X 小于根结点键值,在左子树中继续查找
- 若 X 大于根结点键值,在右子树中继续查找
- 如 X 等于根节点键值,查找结束,返回指向此结点的指针
2. 查找最大和最小元素
- 最大元素一定是在树的最右分支的端结点上
- 最小元素一定是在树的最左分支的端结点上
3. 删除
删除的三种情况:
- 要删除的是叶结点:直接删除,并将其父结点指针置为 NULL
- 要删除的结点只有一个孩子结点:将其父结点的指针指向要删除结点的孩子结点
- 要删除的结点有左、右两棵子树:用右子树的最小元素或左子树的最大元素替代被删除结点
4. 代码实现
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : 二叉搜索树.py
# @Date : 2019/3/28 0028
# @Contact : [email protected]
# @Author: DeepMan
"""
分别在左右子树中进行递归查找
当相等的时候返回
"""
from Tree import *
node_list = [89 ,8 ,64 ,64 ,9, 49, 65 ,146, 4, 61, 5,46]
# 创建一棵树
tree = BinaryTree(10)
for node in node_list:
tree.insert(node, tree)
# 递归查找
def find(x, BST):
if not BST: # 如果树为空 则直接return
return
if x < BST.data:
return find(x, BST.left)
if x > BST.data:
return find(x, BST.right)
if x == BST.data:
return BST
# print(find(10, tree).right.data)
# 非递归查找 对于上面这种 尾递归 可以使用循环来实现
def iterfind(x, BST):
while(BST):
if x < BST.data:
BST = BST.left
if x > BST.data:
BST = BST.right
if x == BST.data:
return BST
return None
# print(iterfind(10, tree).right.data)
# 查找最小值的递归实现**************************************************
def findmin(BST): # 最小值在最左边
if not BST:
return None
elif BST.left:
return findmin(BST.left)
else:
return BST
# print(findmin(tree).data)
# 查找最大值 的 非递归实现 最大元素在最右边
def iterfindmax(BST):
while BST.right:
BST = BST.right
return BST
# print(iterfindmax(tree).data)
# 插入元素的操作
def insert(valve, BST):
"""插入数据, 首先要找到对应插入的位置,再进行插入操作
:param valve:
:param BST:
:return:
"""
if not BST:
BST = BinaryTree(valve)
else:
if valve < BST.data:
BST.left = insert(valve, BST.left)
if valve > BST.data:
BST.right = insert(valve, BST.right)
# 如果已经存在则什么都不做
return BST
# print(iterfindmax(insert(256, tree)).data)
# 二叉树的删除 ***************************************************************
"""
对于要删除节点包含左右儿子节点的情况:
1:取右子树中最小的元素替代 (一定在右子树的最左边,没有左儿子)
2: 取左子树中最大的元素替代 (一定在左子树的最右边,没有右儿子)
"""
def delet(x, BST):
if not BST: # not None 当为None的时候进入
print("do not find ")
elif x < BST.data:
BST.left = delet(x, BST.left)
elif x > BST.data:
BST.right = delet(x, BST.right)
elif x == BST.data: # 这时候就找到了
if BST.left and BST.right: # 如果有两个儿子节点 则利用上面的那种情况进行解决
temp = findmin(BST.right) # 找到右子树的最小元素进行替代
BST.data = temp.data
BST.right = delet(BST.data, BST.right) # 删除那个最小的节点
else: # 被删除节点没有子节点 或 只有一个子节点
if not BST.right: # 右节点为空
BST = BST.left
elif not BST.left: # 左节点为空
BST = BST.right
return BST
bst = delet(146, tree)
print(find(146, bst))