【Python数据结构】——二叉查找树(查找、构建、删除、插入、打印)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2021/7/15 0:34
# @Author  : @linlianqin
# @Site    : 
# @File    : 二叉查找树类实现(查找、创建、删除、插入、遍历).py
# @Software: PyCharm
# @description:

class TreeNode:
	def __init__(self, val, left=None, right=None):
		self.val = val
		self.left = left
		self.right = right

class BST_operation:
	# 二叉查找数元素查找
	# 思路:根据二叉查找树的左小右大的特性,当当前结点值大于target则说明值在左子树,否则在右子树
	def BST_search(self,root, target):
		# 当访问到最后得到的是None,说明元素不存在查找树上
		if root == None:
			return False
		# 当当前结点值等于target时查找成功
		if root.val == target:
			return True
		# 当结点值小于target时,说明目标有可能存在右子树
		elif root.val < target:
			return self.BST_search(root.right, target)
		# 当结点值小于target时,说明目标有可能存在右子树
		if root.val > target:
			return self.BST_search(root.left, target)

	# 二叉查找数元素插入
	# 思路:根据二叉查找树的左小右大的特性,当当前结点值大于target则说明值插入到,否则在右子树
	# 当root == None时,说明就是插入的位置
	def BST_insert(self,root, target):
		# 当值为None,创建新结点
		if root == None:
			root = TreeNode(target)
		# 存在时
		elif root.val == target:
			pass
		elif root.val < target:
			root.right = self.BST_insert(root.right, target)
		elif root.val > target:
			root.left = self.BST_insert(root.left, target)
		return root

	# 二叉查找树构建
	# 根据列表进行二叉查找数的建立
	# 思路:新建一个None结点作为初始头结点,然后进行后面元素的插入
	def BST_create(self,li):
		if len(li) != 0:
			root = TreeNode(li[0])
		else:
			return None
		for i in range(1, len(li)):
			self.BST_insert(root, li[i])
		return root

	# 二叉查找树的删除
	# 删除根节点的处理方法,为了保证删除根节点后依旧是一颗完整的二叉查找树,这里可以用左子树中的最大值和右子树中的最小值来代替根节点,然后在子树中删除相应的叶节点
	# 1)若root值为None,说明二叉树中不存在要删除的值
	# 2)若root值刚好是target,说明已经找到了要删除的结点,进行删除处理操作:
	# a) 如果root没有左右子树了,直接删除结点即可
	# b)如果root还有左子树,则寻找左子树中的最大值,用于替换root,然后在左子树中删除结点
	# c) 如果root还有右子树,则寻找右子树的最小树,用于替换root,然后在右子树中删除结点
	# 3)如果root值大于target,target可能在左子树,递归
	# 4)如果root值小于target,target可能在右子树,递归

	## 寻找二叉查找树以root为根节点的最小权值
	def BST_search_min(self,root):
		if root.left:
			return self.BST_search_min(root.left)
		else:
			return root

	## 寻找二叉查找树以root为根节点的最大权值
	def BST_search_max(self,root):
		if root.right:
			return self.BST_search_max(root.right)
		else:
			return root

	## 删除
	def BST_delete(self,root, target):
		# todo:这里可选
		# 1)若root值为None,说明二叉树中不存在要删除的值
		if root.val == None:
			return

		# 2)如果root值大于target,target可能在左子树,递归
		elif root.val > target:
			root.left = self.BST_delete(root.left, target)

		# 3)如果root值小于target,target可能在右子树,递归
		elif root.val < target:
			root.right = self.BST_delete(root.right, target)

		# 4)若root值刚好是target,说明已经找到了要删除的结点,进行删除处理操作:
		if root.val == target:
			# a) 如果root没有左右子树了,直接删除结点即可
			if root.left is None and root.right is None:
				root = None
			# b)如果root还有左子树,则寻找左子树中的最大值,用于替换root,然后在左子树中删除结点
			elif root.left is not None:
				root = root.left
			# c) 如果root还有右子树,则寻找右子树的最小树,用于替换root,然后在右子树中删除结点
			elif root.right is not None:
				root = root.right
		return root

	# 遍历二叉查找数,中序遍历
	def BST_mid_scan(self,root):
		if root is None:
			return
		# 遍历左子树
		self.BST_mid_scan(root.left)
		# 遍历根节点
		print(root.val, end=',')
		self.BST_mid_scan(root.right)

if __name__ == '__main__':
	li = [5,3,7,4,2,8,6]
	print('li:',li)
	BST = BST_operation()
	print('构建二叉查找树--------------------')
	root = BST.BST_create(li)
	BST.BST_mid_scan(root)
	# 插入
	print("\n插入1--------------------------")
	BST.BST_insert(root,1)
	BST.BST_mid_scan(root)
	# 删除
	print("\n删除6----------------------")
	BST.BST_delete(root,6)
	BST.BST_mid_scan(root)
	# 查找
	print("\n查找--------------------------------")
	print("在二叉树中查找10:",BST.BST_search(root,10))
	print("在二叉树中查找5:",BST.BST_search(root,5))

li: [5, 3, 7, 4, 2, 8, 6]
构建二叉查找树--------------------
2,3,4,5,6,7,8,
插入1--------------------------
1,2,3,4,5,6,7,8,
删除6----------------------
1,2,3,4,5,7,8,
查找--------------------------------
在二叉树中查找10: False
在二叉树中查找5: True

参考:

https://blog.csdn.net/ca___0/article/details/111385872

https://blog.csdn.net/u010089444/article/details/70854510

胡凡——算法笔记

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有情怀的机械男

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值