数据结构-二叉搜索树
二叉搜索树是一颗二叉树且满足性质:
设x是二叉树的一个节点。如果y是x左子树的一个节点,那么y.key ≤ x.key; 如果y是x右子树的一个节点,那么y.key > xkey。
对于根节点,左子树中所有节点的值 < 根节点的值 < 右子树中所有节点的值,任意节点的左、右子树也是二叉搜索树,同样满足这个条件
二叉搜索树的操作:
- 查询
- 插入
- 删除
import random class BiTreeNode: def __init__(self, data): self.data = data self.lchild = None self.rchild = None self.parent = None class BST: def __init__(self, li=None): self.root = None if li: for val in li: self.insert_no_rec(val) # 插入 def insert_no_rec(self, val): # 非递归写法 p = self.root if not p: # 空树 self.root = BiTreeNode(val) return while True: if val < p.data: if p.lchild: p = p.lchild # p指针指向p的左孩子 else: # 左孩子不存在 p.lchild = BiTreeNode(val) p.lchild.parent = p return elif val > p.data: if p.rchild: p = p.rchild else: p.rchild = BiTreeNode(val) p.rchild.parent = p return else: return # 查询 def query_no_rec(self, val): # 非递归写法 p = self.root while p: if p.data < val: p = p.rchild elif p.data > val: p = p.lchild else: return p return None
# 删除时的各个情况 def __remove_node_1(self, node): # 情况1:node是叶子节点 if not node.parent: # 如果是没有父亲的 根节点 self.root = None if node == node.parent.lchild: # node是它父亲的左孩子 node.parent.lchild = None # 将左孩子置为空 else: # 右孩子 node.parent.rchild = None def __remove_node_21(self, node): # 情况2.1:node只有一个左孩子 if not node.parent: # node为根节点时 self.root == node.lchild node.lchild.parent = None elif node == node.parent.lchild: # node在它父亲的左边并且有一个左孩子 node.parent.lchild = node.lchild node.lchild.parent = node.parent else: # node在它父亲的右边并且只有一个左孩子 node.parent.rchild = node.lchild node.lchild.parent = node.parent def __remove_node_22(self, node): # 情况2.2:node只有一个右孩子 if not node.parent: self.root = node.rchild node.rchild.parent = None elif node == node.parent.lchild: # node是它父亲的左孩子并且只有一个右孩子 node.parent.lchild = node.rchild node.rchild.parent = node.parent else: # node是它父亲的右孩子并且只有一个右孩子 node.parent.rchild = node.rchild node.rchild.parent = node.parent
# 删除 def delete(self, val): if self.root: # 不是空树 node = self.query_no_rec(val) if not node: # 要删除的node不存在 return False if not node.lchild and not node.rchild: # 1.叶子节点 self.__remove_node_1(node) elif not node.rchild: # 2.1 只有一个左孩子 self.__remove_node_21(node) elif not node.lchild: # 2.2 只有一个右孩子 self.__remove_node_22(node) else: # 3.两个孩子都有 min_node = node.rchild while min_node.lchild: # 只要左孩子不为空就一直找左孩子 min_node = min_node.lchild node.data = min_node.data # 将node.data直接替换成最后找到的左孩子 # 删除min_node if min_node.rchild: self.__remove_node_22(min_node) else: self.__remove_node_1(min_node) li = list(range(50)) random.shuffle(li) tree1 = BST(li) # tree1.in_order(tree1.root) node = BST(li).root # node 指向根节点 print(tree1.query(node, 5).data) tree1.delete(4) # print(tree1.query_no_rec(4).data) tree1.in_order(tree1.root)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」