python coding with ChatGPT 打卡第22天| 二叉搜索树的操作:插入、删除、修剪、转换

相关推荐
python coding with ChatGPT 打卡第12天| 二叉树:理论基础
python coding with ChatGPT 打卡第13天| 二叉树的深度优先遍历
python coding with ChatGPT 打卡第14天| 二叉树的广度优先遍历
python coding with ChatGPT 打卡第15天| 二叉树:翻转二叉树、对称二叉树
python coding with ChatGPT 打卡第16天| 二叉树:完全二叉树、平衡二叉树、二叉树的所有路径、左叶子之和
python coding with ChatGPT 打卡第17天| 二叉树:找树左下角的值、路径总和
python coding with ChatGPT 打卡第18天| 二叉树:从中序与后序遍历序列构造二叉树、最大二叉树
python coding with ChatGPT 打卡第19天| 二叉树:合并二叉树
python coding with ChatGPT 打卡第20天| 二叉搜索树:搜索、验证、最小绝对差、众数
python coding with ChatGPT 打卡第21天| 二叉树:最近公共祖先

文章目录

  • 二叉搜索树的插入操作
    • Key Points
    • 相关题目
    • 视频讲解
    • 重点分析
  • 删除二叉搜索树的节点
    • Key Points
    • 相关题目
    • 视频讲解
    • 重点分析
  • 修剪二叉搜索树
    • Key Points
    • 相关题目
    • 视频讲解
    • 重点分析
  • 将有序数组转换为二叉搜索树
    • Key Points
    • 相关题目
    • 视频讲解
    • 重点分析
  • 把二叉搜索树转换为累加树
    • Key Points
    • 相关题目
    • 视频讲解
    • 重点分析

二叉搜索树的插入操作

Key Points

BST的性质:对于每个节点,其左子树只包含小于当前节点的数,其右子树只包含大于当前节点的数。

相关题目

701. 二叉搜索树的插入操作

视频讲解

二叉搜索树的插入操作

重点分析

在这里插入图片描述

方法一:递归法

def insertIntoBST(root, val):# 如果当前节点为空,创建一个新节点并返回if not root:return TreeNode(val)# 如果新值小于当前节点的值,递归地插入到左子树if val < root.val:root.left = insertIntoBST(root.left, val)# 如果新值大于当前节点的值,递归地插入到右子树else:root.right = insertIntoBST(root.right, val)# 返回根节点return root

方法二:迭代法

def insertIntoBST(root, val):if not root:return TreeNode(val)current = rootwhile True:if val < current.val:if current.left:current = current.leftelse:current.left = TreeNode(val)break  # 插入完成,退出循环else:  # val > current.valif current.right:current = current.rightelse:current.right = TreeNode(val)break  # 插入完成,退出循环return root

删除二叉搜索树的节点

Key Points

分类讨论:

  1. 没找到节点
  2. 叶子节点
  3. 只有一个孩子的节点
  4. 有两个孩子的节点

相关题目

450. 删除二叉搜索树种的节点

视频讲解

调整二叉树的结构最难

重点分析

我们需要从根节点开始,使用二叉搜索树的性质来定位要删除的节点。这意味着:

如果 key 小于当前节点的值,则我们应该在左子树中查找 key。
如果 key 大于当前节点的值,则我们应该在右子树中查找 key。
如果 key 等于当前节点的值,那么我们就找到了要删除的节点。

例如:删除如下二叉树值为20的节点
在这里插入图片描述

其中,删除有两个孩子的节点是最重要的,主要有两种思路:

  1. 用删除节点的左孩子替换删除节点,把删除节点的右孩子整个放在左孩子的最大节点的右侧。
    • 优点:不用递归调用删除节点的函数
    • 缺点:新二叉树结构改变会很大(如:平衡->不平衡)
  2. 用删除节点的左孩子的最大值替换删除节点,然后递归删除左孩子的最大节点。
    • 优点:新二叉树结构变化较小
    • 缺点:需要递归调用

方法一:
在这里插入图片描述方法二:
在这里插入图片描述
方法一:
递归法:

def get_max_child(node):while node.right:node = node.rightreturn nodedef deleteNode(root, key):if not root:return rootif root.val > key:root.left = deleteNode(root.left, key)return root  # 返回root才完整if root.val < key:root.right = deleteNode(root.right, key)return rootelse:if not root.left and not root.right:return Noneif not root.left:return root.rightif not root.right:return root.leftnode = get_max_child(root.left)node.right = root.rightreturn root.left

写递归的逻辑:
某个情形的逻辑要完整(return)

方法一:
迭代法

def deleteNode(root, key):current = rootparent = Nonewhile current:if current.val > key:parent = currentcurrent = current.leftelif current.val < key:parent = currentcurrent = current.rightelse:if not current.left and not current.right:if not parent:return Noneelse:if parent.left == current:parent.left = Noneelse:parent.right = Nonereturn rootelif not current.right:if not parent:return current.leftelse:if parent.left == current:parent.left = current.leftelse:parent.right = current.leftreturn rootelif not current.left:if not parent:return current.rightelse:if parent.left == current:parent.left = current.rightelse:parent.right = current.rightreturn rootelse:node = get_max_child(current.left)node.right = current.rightif not parent:return current.leftelse:if parent.left == current:parent.left = current.leftelse:parent.right = current.leftreturn rootreturn root

迭代法注意考虑parent为None的情况

方法二:
递归法

def deleteNode(root, key):if not root:return rootif root.val > key:root.left = deleteNode(root.left, key)return rootif root.val < key:root.right = deleteNode(root.right, key)return rootelse:if not root.left and not root.right:return Noneif not root.left:return root.rightif not root.right:return root.leftnode = get_max_child(root.left)root.val = node.valroot.left = deleteNode(root.left, node.val)return root

方法二:
迭代法

    current = rootparent = Nonewhile current:if current.val > key:parent = currentcurrent = current.leftelif current.val < key:parent = currentcurrent = current.rightelse:if not current.left and not current.right:if not parent:return Noneelse:if parent.left == current:parent.left = Noneelse:parent.right = Nonereturn rootelif not current.right:if not parent:return current.leftelse:if parent.left == current:parent.left = current.leftelse:parent.right = current.leftreturn rootelif not current.left:if not parent:return current.rightelse:if parent.left == current:parent.left = current.rightelse:parent.right = current.rightreturn rootelse:node = get_max_child(current.left)current.val = node.valcurrent.left = deleteNode(current.left, node.val)return rootreturn root

修剪二叉搜索树

Key Points

易错点:

        3/ \0   4\2/1

[1,3]

相关题目

669. 修剪二叉搜索树

视频讲解

如何修剪二叉树

重点分析

方法一: 递归法

def trimBST(root, low, high):if not root:return None# 如果节点值小于low,那么它的左子树都不在范围内,应修剪掉左子树if root.val < low:root = trimBST(root.right, low, high)# 如果节点值大于high,那么它的右子树都不在范围内,应修剪掉右子树elif root.val > high:root = trimBST(root.left, low, high)# 如果节点值在[low, high]范围内,递归修剪其左右子树else:root.left = trimBST(root.left, low, high)root.right = trimBST(root.right, low, high)return root

方法二:迭代法

def trimBST(root, low, high):dummy = TreeNode(float("inf"))  # 创建虚拟父节点dummy.left = root  # 将原树的根节点作为虚拟父节点的左子节点stack = [(dummy, root, True)]  # 初始化栈,包含虚拟父节点、根节点、根节点是左子节点的信息while stack:parent, node, isLeft = stack.pop()  # 弹出当前节点及其父节点信息if not node:continue# 如果当前节点值小于low,则需要修剪当前节点及其左子树if node.val < low:# 根据是左子节点还是右子节点,更新父节点的链接if isLeft:parent.left = node.right  # 将右子节点(可能在范围内)连接到父节点else:parent.right = node.rightstack.append((parent, node.right, isLeft))  # 继续检查右子节点# 如果当前节点值大于high,逻辑相同,但修剪右子树elif node.val > high:if isLeft:parent.left = node.leftelse:parent.right = node.leftstack.append((parent, node.left, isLeft))# 如果当前节点值在[low, high]范围内,保留节点,继续检查其子节点else:stack.append((node, node.left, True))stack.append((node, node.right, False))return dummy.left  # 返回修剪后的新树的根节点

这段代码使用了一个栈来追踪遍历过程中的节点以及它们的父节点和是否为左子节点的信息。对每个节点,我们检查它是否需要被修剪(即它的值是否在 [low, high] 范围之外)。如果是,则根据它是左子节点还是右子节点,更新父节点的相应链接。如果节点的值在范围内,我们将继续处理它的子节点。

请注意,这个方法虽然避免了递归,但逻辑复杂度增加了,特别是在管理父节点和子节点关系时。对于二叉树的修改操作,递归方法通常更为直观和易于理解。

在这里插入图片描述

将有序数组转换为二叉搜索树

Key Points

分而治之的策略:选取中间元素作为根节点,然后对左右子数组分别执行同样的操作

相关题目

108将有序数组转换为二叉搜索树

视频讲解

构造平衡二叉搜索树

重点分析

关键在于每次都要选取数组中间的元素作为树的根节点,这样可以确保树的左右两边保持平衡。

方法一:递归法

def sortedArrayToBST(nums):if not nums:return Nonemid = len(nums) // 2root_val = nums[mid]root = TreeNode(root_val)root.left = sortedArrayToBST(nums[:mid])root.right = sortedArrayToBST(nums[mid+1:])return root

方法二:迭代法

def sortedArrayToBST(nums):if not nums:return None# 用于保存处理节点的栈node_stack = []# 用于保存数组范围的栈range_stack = [(0, len(nums) - 1)]# 创建一个虚拟的根节点root = TreeNode(0)node_stack.append((root, True))while range_stack:left, right = range_stack.pop()parent, is_left = node_stack.pop()if left > right:continuemid = (left + right) // 2# 创建当前节点current_node = TreeNode(nums[mid])# 将当前节点连接到父节点if is_left:parent.left = current_nodeelse:parent.right = current_node# 处理左子树node_stack.append((current_node, True))range_stack.append((left, mid - 1))# 处理右子树node_stack.append((current_node, False))range_stack.append((mid + 1, right))return root.left

把二叉搜索树转换为累加树

Key Points

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
在这里插入图片描述

相关题目

538. 把二叉搜索树转换为累加树

视频讲解

二叉树完结

重点分析

方法一:递归法

class Solution(object):def __init__(self):self.sum_value = 0def convertBST(self, root):""":type root: TreeNode:rtype: TreeNode"""if not root:return rootroot.right = self.convertBST(root.right)self.sum_value += root.valroot.val = self.sum_valueroot.left = self.convertBST(root.left)return root

方法二:迭代法 反向中序遍历

按照反向中序遍历(右->节点->左)的顺序,使用栈来迭代地遍历树

def convertBST(root):if not root:return rootcurrent = rootstack = []sum_value = 0while current or stack:# 将当前节点及其所有右子节点压入栈while current:stack.append(current)current = current.rightcurrent = stack.pop() # 访问栈顶元素(当前最大节点)sum_value += current.valcurrent.val = sum_valuecurrent = current.left # 转向左子树return root

方法二:迭代法 统一迭代法(颜色标记)
详见 python coding with ChatGPT 打卡第13天| 二叉树的深度优先遍历 中的迭代遍历 拓展 统一的迭代法

def convertBST(root):if not root:return rootWHITE = 0  # 使用常量来提高代码可读性GREY = 1stack = [(root, WHITE)]sum_value = 0  # 累加变量,用于更新节点的值while stack:node, color = stack.pop()if color == WHITE: # 节点首次访问,先处理右子节点stack.append((node, GREY))  if node.right:stack.append((node.right, WHITE))else: # 节点第二次访问,更新节点值并处理左子节点sum_value += node.valnode.val = sum_valueif node.left:stack.append((node.left, WHITE))return root

GPT4点评:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/742555.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot集成对象存储服务Minio

MinIO 是一个基于 Apache License v2.0 开源协议的对象存储服务。它兼容亚马逊 S3 云存储服务接口&#xff0c;非常适合于存储大容量非结构化的数据&#xff0c;例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等&#xff0c;而一个对象文件可以是任意大小&#xff0c;从…

IP数据报格式

每一行都由32位比特&#xff0c;即4个字节组成&#xff0c;每个格子称为字段或者域。IP数据报由20字节的固定部分和最大40字节的可变部分组成。 总长度 总长度为16个比特&#xff0c;该字段的取值以字节为单位&#xff0c;用来表示IPv4数据报的长度(首部长度数据载荷长度)最大…

基于java+springboot+vue实现的停车场管理系统(文末源码+Lw)23-258

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统停车场管理系统信息管理难度大&#xff0c;容错率低&…

【Axure高保真原型】下拉列表切换图表

今天和大家分享通过下拉列表动态切换统计图表的原型模板&#xff0c;我们可以通过下拉列表选择要显示的图表&#xff0c;包括柱状图、条形图、饼图、环形图、折线图、曲线图、面积图、阶梯图、雷达图&#xff1b;而且图表数据可以在左侧表格中动态维护&#xff0c;包括增加修改…

《你是什么垃圾-弹幕版》

你是什么垃圾-弹幕版 类型&#xff1a;垃圾分类 视角&#xff1a;2d 乐趣点&#xff1a;弹幕交互&#xff0c;热点追踪 时间&#xff1a;2021 个人职责&#xff1a; 所有程序部分的设计开发 此游戏是某个早晨&#xff0c;在早点铺子吃米线的时候构思出来的。当时正是&#xff0…

bpmn-js系列之Viewer

上一篇文章『bpmn-js系列之Modeler、以及流程编辑界面的优化』介绍了bpmn-js的modeler模式下的一些开发配置&#xff0c;这篇文章将会介绍Viewer模式的使用 以下演示代码基于上一节搭建好的vue环境&#xff0c;使用bpmn版本为当前最新版7.3.0 基本使用 Viewer的使用与Modele…

【基础CSS】

本文章属于学习笔记&#xff0c;在https://www.freecodecamp.org/chinese/learn/2022/responsive-web-design/中练习 二、 CSS 样式&#xff0c;新建一个文件.css&#xff0c;该文件不含有style标签 <style>. h1&#xff0c;h2&#xff0c;p{ text-align&#xff1a;ce…

Skywalking(9.7.0) 告警配置

图片被吞&#xff0c;来这里看吧&#xff1a;https://juejin.cn/post/7344567669893021736 过年前一天发版&#xff0c;大家高高兴兴准备回家过年去了。这时候老板说了一句&#xff0c;记得带上电脑&#xff0c;关注用户反馈。有紧急问题在高速上都得给我找个服务区改好。 但是…

C++初阶

1.缺省参数 给缺省参数的时候&#xff0c;不能声明&#xff0c;定义同时给&#xff0c;只能声明的时候给缺省参数&#xff0c;同时给程序报错&#xff1b; 2.函数重载 C语言不允许同名函数的存在&#xff0c;函数名不能相同&#xff0c;C引入函数重载&#xff0c;函数名可以…

IDEA启动时,电脑非常的卡

选择Help -> Change memory Settings 把启动内存调大一点就行了&#xff0c;反正要超过你平时使用IDEA时使用到的内存大小就行。 原因解释&#xff1a; JVM在运行时会回收新生代和老年代的垃圾&#xff0c;新生代无法回收的对象&#xff0c;比如&#xff1a;回收15次都没有…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的农作物害虫检测系统(深度学习模型+UI界面+训练数据集)

摘要&#xff1a;开发农作物害虫检测系统对于提高农业生产效率和作物产量具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个农作物害虫检测系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&#xff0…

前端请求到 SpringMVC 的处理流程

1. 发起请求 客户端通过 HTTP 协议向服务器发起请求。 2. 前端控制器&#xff08;DispatcherServlet&#xff09; 这个请求会先到前端控制器 DispatcherServlet&#xff0c;它是整个流程的入口点&#xff0c;负责接收请求并将其分发给相应的处理器。 3. 处理器映射&#xf…

SpringBoot项目中出现不同端口跨域问题,如何解决?

方法一&#xff1a;比较繁琐&#xff0c;适合少量Controller控制器类 方法二 &#xff1a;需要写一个全局的配置文件即可 在如图所示的common目录下新建一个CorsConfig的class文件 具体代码展示&#xff1a; import org.springframework.context.annotation.Bean; import o…

前端Vue列表组件 list组件:实现高效数据展示与交互

前端Vue列表组件 list组件&#xff1a;实现高效数据展示与交互 摘要&#xff1a;在前端开发中&#xff0c;列表组件是展示数据的重要手段。本文将介绍如何使用Vue.js构建一个高效、可复用的列表组件&#xff0c;并探讨其在实际项目中的应用。 效果图如下&#xff1a; 一、引言…

功能测试--APP性能测试

功能测试--APP性能测试 内存数据查看内存测试 CPU数据查看CPU测试 流量和电量的消耗流量测试流量优化方法电量测试电量测试场景&#xff08;大&#xff09; 获取启动时间启动测试--安卓 流畅度流畅度测试 稳定性稳定性测试 内存数据查看 内存泄露:内存的曲线持续增长(增的远比减…

git上拉下来的web项目,只有一个.git路径解决

代码拉下来的时候&#xff0c;web项目路径只有一个.git&#xff0c;可能指没有致命分支&#xff1a; 用idea打开web项目&#xff1b;切换到对应的分支即可

基于Ambari搭建大数据分析平台

一、部署工具简介 1. Hadoop生态系统 Hadoop big data ecosystem in Apache stack 2. Hadoop的发行版本 Hadoop的发行版除了Apache的开源版本之外&#xff0c;国外比较流行的还有&#xff1a;Cloudera发行版(CDH)、Hortonworks发行版&#xff08;HDP&#xff09;、MapR等&am…

代理IP是否会导致网络连接变慢?

目录 一、代理IP的工作原理及其在网络中的作用 二、代理IP可能导致网络连接变慢的因素 三、案例分析 四、优化代理IP使用的建议 五、总结 在网络世界中&#xff0c;代理IP的使用非常普遍&#xff0c;尤其是在需要隐藏真实IP地址、访问受限资源或进行网络爬虫等场景下。然而…

如何查看mnist数据集的图片

import numpy as np import matplotlib.pyplot as pltdef read_mnist_images(filename):with open(filename, rb) as f:# 读取魔术数字、图像数量、行数、列数magic_number int.from_bytes(f.read(4), big)number_of_images int.from_bytes(f.read(4), big)rows int.from_by…

UE4案例记录

UE4案例记录&#xff08;制作3D角色显示在UI中&#xff09; 制作3D角色显示在UI中 转载自youtube视频 https://www.youtube.com/channel/UCC8f6SxKJElVvaRb7nF4Axg 新建项目 创建一个Actor 场景组件->摄像机组件->场景捕获组件2D&#xff0c;之后添加一个骨骼网格体…